Дружим virt-manager с удаленной системой поверх tls

в 20:24, , рубрики: Без рубрики

На работе мы активно используем виртуализацию на базе qemu/kvm через libvirt. Сам я давно пересел на linux и также использую qemu/kvm на своей локальной машине, при этом, часто применяю графический virt-manager для настройки различных параметров ВМ. Хотелось использовать его и для управления гипервизорами на удаленных серверах. О том как это сделать и будет статья в виде пошаговой инструкции(по факту это перевод и «сведение в едино» официальной документации).

Подготовка

Подразумевается, что все действия делаются на «ноде виртуализации» ( где стоит libvirtd, в данном случае это CentOS 6 ) и selinux отключен. Выполняем в консоли:

mkdir /tmp/certs
cd /tmp/certs

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

mkdir ca
cd ca

Создаем шаблон с параметрами корневого сертификата (CA):

cat > certificate_authority_template.info << 'EOF'
cn = Name of your organization
ca 
cert_signing_key 
expiration_days = 3650 
EOF

«Name of your organization» — соответственно имя вашей организации в латинице, срок действия сертификата- 10 лет.

Гененрируем секретный ключ для CA:

(umask 277 && certtool --generate-privkey > certificate_authority_key.pem)

Генерируем самоподписанный CA:

certtool --generate-self-signed 
            --template certificate_authority_template.info 
            --load-privkey certificate_authority_key.pem 
            --outfile certificate_authority_certificate.pem

Генерируем сертификат для «ноды виртуализации» ( где стоит libvirtd)

cd ..
mkdir kvm_host
cd  kvm_host

Создаем шаблон с параметрами сертификата для «ноды виртуализации»:

cat > host_server_template.info << 'EOF'
organization = Name of your organization
cn = server.name 
tls_www_server 
encryption_key 
signing_key 
EOF

«server.name»- dns имя «ноды виртуализации», для которой генерируется сертификат,

Генерируем секретный ключ для «ноды виртуализации»:

(umask 277 && certtool --generate-privkey > host_server_key.pem)

Генерируем сертификат для нашей «ноды виртуализации»:

certtool --generate-certificate 
            --template host_server_template.info 
            --load-privkey host_server_key.pem 
            --load-ca-certificate ../ca/certificate_authority_certificate.pem 
            --load-ca-privkey ../ca/certificate_authority_key.pem 
            --outfile host_server_certificate.pem

Генерируем сертификат для клиентского подключения.

cd ..
mkdir client
cd client

Создаем шаблон с параметрами сертификата для клиента:

cat > client_template.info << 'EOF'
country = RU 
state = State
locality = City
organization = Name of your organization
cn = client.host
tls_www_client 
encryption_key 
signing_key 
EOF

«client.host»- dns имя клиента, state и locality заполняем по вашему усмотрению.

Генерируем секретный ключ для клиента:

(umask 277 && certtool --generate-privkey > client_key.pem)

Генерируем сертификат для клиента:

 certtool --generate-certificate 
            --template client_template.info 
            --load-privkey client_key.pem 
            --load-ca-certificate ../ca/certificate_authority_certificate.pem 
            --load-ca-privkey ../ca/certificate_authority_key.pem 
            --outfile client_certificate.pem

Подключение сертификатов/ключей к libvirt

cd /tmp/certs

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

mkdir -p /etc/pki/libvirt/private
chmod 755 /etc/pki/libvirt
chmod 750 /etc/pki/libvirt/private
cp ./ca/certificate_authority_certificate.pem /etc/pki/libvirt/cacert.pem
cp ./kvm_host/host_server_certificate.pem /etc/pki/libvirt/servercert.pem
cp ./kvm_host/host_server_key.pem  /etc/pki/libvirt/private/serverkey.pem
ln -s /etc/pki/libvirt/cacert.pem  /etc/pki/CA/
chgrp qemu /etc/pki/libvirt 
              /etc/pki/libvirt/servercert.pem 
              /etc/pki/libvirt/private 
              /etc/pki/libvirt/private/serverkey.pem
chmod 440 /etc/pki/libvirt/servercert.pem
chmod 444 /etc/pki/libvirt/cacert.pem
chmod 640 /etc/pki/libvirt/private/serverkey.pem

Права 640 на на server-key.pem нужны, чтобы можно было использовать этот же ключ для vnc соединения, при это утилита virt-pki-validate будет ругаться что права должны быть 600- игнорируем.

Подключение сертификатов/ключей к vnc

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

mkdir /etc/pki/libvirt-vnc
ln -s /etc/pki/libvirt/cacert.pem /etc/pki/libvirt-vnc/ca-cert.pem
ln -s /etc/pki/libvirt/servercert.pem /etc/pki/libvirt-vnc/server-cert.pem
ln -s /etc/pki/libvirt/private/serverkey.pem /etc/pki/libvirt-vnc/server-key.pem
chgrp qemu /etc/pki/libvirt-vnc
chmod 750 /etc/pki/libvirt-vnc 

Настройка демона libvirtd

В файле /etc/libvirt/libvirtd.conf нужно установиться следующие значения для соответствующих параметров:

listen_tls = 1 
tls_port = "16514" 
auth_tls = "none" 
key_file = "/etc/pki/libvirt/private/serverkey.pem" 
cert_file = "/etc/pki/libvirt/servercert.pem" 
ca_file = "/etc/pki/libvirt/cacert.pem" 
crl_file = "/etc/pki/libvirt/crl.pem" 
#tls_allowed_dn_list = ["DN1", "DN2"]
log_level = 3 
log_outputs="4:syslog:libvirtd 3:file:/var/log/libvirt/libvirt.log"
audit_level = 2 
audit_logging = 1 
keepalive_interval = 5 
keepalive_count = 5

В результате мы включим tls и настроим логирование.
В tls_allowed_dn_list прописывается dn( Distinguished Name) сертификатов, которым можно будет подключаться к libvirtd
В файле /etc/sysconfig/libvirtd параметр LIBVIRTD_ARGS должен быть выставлен в «--listen»:

LIBVIRTD_ARGS="--listen"

Настройка демона qemu/kvm

В файле /etc/libvirt/qemu.conf нужно установиться следующие значения для соответствующих параметров:

vnc_tls = 1 
vnc_tls_x509_verify = 1 
vnc_allow_host_audio = 0 
cgroup_controllers = [ "cpu", "devices", "memory", "blkio", "cpuset", "cpuacct" ] 
save_image_format = "lzop" 
clear_emulator_capabilities = 1

Так мы включим tls для подключения по vnc виртуальных машин, отключим передачу audio( нам оно не надо, если вам нужно- оставьте включенным), включим сжатие для снапшотов памяти(пригодится для живых бэкапов, если кому интересно, мы бэкапим так, так как раньше выложил там- привожу в виде ссылки), а также включим соответствующие группы cgroups( вообще оно включено по-умолчанию, но задал жестко)
Только после этой правки перезапускаем libvirtd:

service libvirtd restart

Для уже запущенных виртуальных машин подключение по vnc поверх tls будет возможно только после их выключения и повторного включения( virsh shutdown/start)

Настройка iptables

Для подключения к libvirtd и vnc в цепочку INPUT нужно внести следующие правила( если используете iptables):

iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 16514 -j ACCEPT
iptables -I INPUT -m state --state NEW -s 192.168.40.0/24 -m tcp -p tcp --dport 5900:6000 -j ACCEPT

Подразумевается, что vnc консоли будут вистеть на портах от 5900 до 6000. После этого сохранить действующие правила iptables командой:

iptables-save>/etc/sysconfig/iptables

Если у вас уже есть с самоподписанный корневой сертификат/клиентские сертификаты

В таком случае выполните все пункты за исключение 1. и 2., при этом указывая ваши пути до корневого сертификата и его ключа в соответствующих параметрах(--load-ca-certificat, --load-ca-privkey), по необходимости пропустите пункт 4., если для необходимых клиентов сертификаты уже сгенерированы.

Настройка клиента( Linux )

Под Linux в данном случае подразумевается Centos/Fedora
Выполняется на удаленной системе с которой будет происходить администрирование «ноды виртуализации».
Для начала надо создать папки для соответствующих сертификатов:

mkdir -m 750 -p /etc/pki/libvirt/private
mkdir -m 700 ~/.pki/libvirt-vnc

Далее положить соответствующие файлы с сервера по необходимым путям на локальной машине, с которой будет происходить подключение:

/tmp/certs/ca/certificate_authority_certificate.pem положить в /etc/pki/CA/cacert.pem
/tmp/certs/client/client_key.pem положить в /etc/pki/libvirt/private/clientkey.pem
/tmp/certs/client/client_certificate.pem положить в /etc/pki/libvirt/clientcert.pem

chmod 444 /etc/pki/CA/cacert.pem
chmod 440 /etc/pki/libvirt/clientcert.pem  /etc/pki/libvirt/private/clientkey.pem
chown -R root:wheel /etc/pki/libvirt
cd ~/.pki/libvirt-vnc/
ln -s /etc/pki/libvirt/clientcert.pem clientcert.pem
ln -s /etc/pki/libvirt/private/clientkey.pem clientkey.pem

С такими настройками к libvirtd/vnc на удаленом сервере смогут подключаться локальные пользователи состоящие в группе wheel и пользователь root.

Пример:

virsh:

virsh -c qemu+tls://server.name/system,
virsh -c qemu+tls://kvm_server.local/system

ВАЖНО! server.name здесь- это именно то имя, что мы указывали при генерации сертификата для «ноды виртуализации»( поле cn сертификата), оно должно корректно определяться в ip на клиенте.

Virt-manager:

В virt-manager выбирать тип подключения- «ssl/tls с сертификатами», имя пользователя-пустое, имя хоста- server.name, о котором говорилось выше.

Virt-viewer:

virt-viewer -c qemu+tls://server.name/system имя_вм

Настройка клиента( Windows, только доступ к vnc консоли )

Выполняется на удаленной системе с которой будет происходить администрирование «ноды виртуализации».
Подключаться можно через:

virt-viewer

мне заставить работать не удалось

ssvnc

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

cd /tmp/certs/client
cat client_certificate.pem client_key.pem >client.pem

Берем с сервера получившийся client.pem и /tmp/certs/ca/certificate_authority_certificate.pem
Запускаем ssvnc- в основном окне ставим «Use SSL», нажимаем «Certs» в «MyCerts» указываем путь к client.pem, в «ServerCert» указываем путь к certificate_authority_certificate.pem, далее жмем «Options» -> «Advanced» и ставим галочку напротив «Server uses Vencrypt ssl encryption». В основном окне в поле «Vnc Host:Display» указываем соответственно адрес сервера и номер vnc порта. Жмем «Connect».

Результат:

В итоге мы можем управлять нашими виртуальными машинами локально через virsh,virt-manager( доступны только те функции, которые поддерживает сервер). Минусы данного решения, что удаленное управление ВМ не отображается в логах ( или мне не удалось этого добиться), тоесть в логах не будет видно, что выключение/etc инициализировал такой-то пользователь с такого-то ip.

Ссылки по теме

wiki.libvirt.org/page/TLSSetup
wiki.libvirt.org/page/VNCTLSSetup

Автор: saamich

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js