Продолжаем поднимать домашнюю лабу с преферансом и курсистками. В прошлой серии мы поговорили про сеть (с которой всё начинается), теперь же мы поговорим про вещи более практичные – доступ к виртуалкам извне с помощью reverse proxy, организацию ssl-подключения при помощи бесплатных сертификатов от Let’s Encrypt и немного посмотрим на плейбуки ansible, с помощью которых удобно раскатывать новые машины и готовить их к работе.
0. Disclaimer
Для начала о том, чего тут НЕ будет.
– Здесь не будет описываться установка VMWare или Debian
– Здесь не будет описываться настройка Mikrotik “с нуля”
– Здесь не будет описываться установка пакетов через apt (будь то ansible, zabbix или apache)
Я предполагаю, что компетенция моих читателей достаточна для того, чтобы не только прочитать всё то, что написано ниже, но и применять на практике с умом и пониманием, что вообще делается и для чего.
1. Настройка Reverse-proxy
Зачем нужен reverse proxy? Например, когда вам нужно отделить фронт-энд и бэкэнд. В качестве бэкэнда может выступать Tomcat, или вообще самописное приложение, которое выпускать в интернет “как есть” просто опасно. Или, к примеру, вам нужно выставить несколько веб-приложений за одним ip-адресом. Если все лежит на одной машине, проблем нет – VirtualHost спасёт отца русской демократии. А если нет? Если каждое приложение – это отдельная ВМ или docker-контейнер? Вот тут нам и пригодится reverse-proxy.
“Правильные пацаны” считают, что поднимать прокси на apache не нужно – “дорого” по ресурсам, меньше гибкости и т.д. Но для меня Apache подошёл как нельзя кстати – во-первых, я с ним банально больше работал, а во-вторых, у меня уже были нужные конфиги, и не хотелось переделывать их под nginx.
Для включения режима прокси надо установить следующие пакеты:
1 | apt-get install apache2 libapache2-mod-proxy-html libxml2-dev |
А затем включить модули apache:
1 | a2enmod proxy && a2enmod ssl && a2enmod cache && a2enmod proxy_connect && a2enmod proxy_html && a2enmod rewrite && a2enmod cache && a2enmod disk_cache |
Не забудьте перезапустить apache.
Возможно, для вашего приложения потребуются еще какие-то модули. Это можно узнать в документации или эмпирически ;)
Теперь делаем конфиг для нашего приложения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <VirtualHost *:80> ServerName jira.nixman.info ProxyPreserveHost On <Proxy *> Order deny,allow Allow from all </Proxy> ProxyPass / http://192.168.88.186:8080/ ProxyPassReverse / http://192.168.88.186:8080/ <Location /> Order allow,deny Allow from all </Location> ErrorLog ${APACHE_LOG_DIR}/jira-error.log CustomLog ${APACHE_LOG_DIR}/jira-access.log combined </VirtualHost> |
Из конфига понятно, что мы перекидываем запросы, пришедшие на адрес jira.nixman.info:80 внутрь локалки, на порт 8080.
Никакой фильтрации или особо заковыристых опций я не добавлял, так что случай можно считать простейшим (хотя и рабочим).
1.1 Зачем нужен SSL-offload
Делать сайты без https-версии в последнее время становится моветоном. Особенно, когда появился Let’s Encrypt, c его абсолютно бесплатными сертификатами, которые, к тому же, действуют всего три месяца, что побуждает к автоматизации процесса их продления.
Собственно SSL-offload – это механизм, при котором данные шифруются только между клиентом и прокси-сервером, на котором SSL-сертификат снимается, и дальше трафик до сервера идёт уже нешифрованный.
Пример конфига с ssl-offload ниже:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <IfModule mod_ssl.c> <VirtualHost *:443> ServerAdmin webmaster@nixman.info ServerName jira.nixman.info ServerAlias *jira.nixman.info DocumentRoot /var/www SSLOptions +StrictRequire SSLEngine on SSLCertificateFile /etc/letsencrypt/live/jira.nixman.info/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/jira.nixman.info/privkey.pem BrowserMatch "MSIE [2-6]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0 BrowserMatch "MSIE [17-9]" \ ssl-unclean-shutdown SSLProtocol all -SSLv2 -SSLv3 SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA SSLHonorCipherOrder on ErrorLog ${APACHE_LOG_DIR}/jira-ssl-error.log CustomLog ${APACHE_LOG_DIR}/jira-ssl-access.log combined ProxyPass / http://192.168.88.186:8080/ ProxyPassReverse / http://192.168.88.186:8080/ </VirtualHost> </IfModule> |
Как вы видите, конфиг, по сути, объединяет в себе предыдущий вариант (с http без ssl) и ssl-секцию обычного VirtualHost, как он обычно настраивается в Apache. При этом на хосте, куда проксируется трафик, может висеть вообще что угодно (у меня это Tomcat с Jira).
Инструкцию по получению сертификатов тут приводить не буду – во-первых, у каждого свой, удобный ему метод (а кто-то вообще до сих пор пользует годичные startssl и wosign), а во-вторых многочисленные how-to на эту тему (включая официальные) весьма просты и гуглятся буквально за несколько секунд.
2. Бонус: полезные плейбуки ansible
Я только в начале пути освоения ansible, но кое-какие из плейбуков уже пригодились.
Например, вот так можно подготовить машину “с нуля” до какого-то нужного уровня:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | - hosts: all user: snake become: true become_method: sudo tasks: - name: Add user action: user name=ansible password=VeRy$eCrEtP@$sw0rD groups=sudo - name: Allow 'sudo' group to have passwordless sudo lineinfile: dest: /etc/sudoers state: present regexp: '^%sudo' line: '%sudo ALL=(ALL) NOPASSWD: ALL' - authorized_key: user: ansible state: present key: "{{ lookup('file', '/home/ansible/.ssh/id_rsa.pub') }}" - name: Software install apt: name={{item}} state=latest with_items: - htop - mc - nano - ntpdate - ntp - tcpdump - traceroute - telnet - curl - name: NTP daemon enable service: name=ntp enabled=yes - name: PermitRootLoginSSH lineinfile: dest=/etc/ssh/sshd_config regexp="^MaxSessions 10" insertafter="^#MaxSessions 10" line="PermitRootLogin no" |
В этом плейбуке мы добавляем пользователя ansible (обратите внимание, он добавляется в группу sudo, а группе даётся право запускать sudo без дополнительного ввода пароля. Не делайте такое в продакшене!), копируем ему наш открытый ключ, чтобы в будущем ходить на машину без ввода пароля, потом ставим начальный набор софта, а заодно запрещаем ходить по ssh руту.
Т.к. подразумевается, что у машина у нас “с нуля”, то нужно задать пользователя, от которого будет выполняться плейбук в системе, а так же указать, что пароли (обычный и sudo) нужно запросить:
1 | ansible@master:~$ ansible-playbook -latlassian.snake.local new.yml -u snake -k -K |
А вот таким плейбуком можно обновить пакеты разом на всех хостах. В продакшене так делать нельзя, но в лабе – почему бы и нет?
1 2 3 4 5 6 7 8 9 10 | - hosts: debian user: ansible become: true become_method: sudo tasks: - name: Update apt cache apt: update_cache=yes - name: Update packets apt: upgrade=full |
Углубляться дальше не буду, но думаю, что если перед вами стоит какая-то более-менее типовая задача, то “про неё тоже есть плейбук”.
На этом всё. Думаю, в процессе добавления новых фишечек будут появляться новые серии (навскидку – хочется поднять внутри локальной сети ipv6), ну а пока – до новых встреч в эфире!