Unifi Controller + Nginx. HTTP & HTTPS

image

Коротка суть:

Покрокова інструкція по проксированию Unifi-контролера через Nginx по http або https.
Конфіги, зрозумілі приклади, коментарі.

Пролог:

Наша компанія займається розробкою мобільних додатків, і як ви могли здогадатися, в офісі знаходиться величезна кількість різних девайсів, всі вони люблять Wi-Fi і не просто Wi-Fi, а безшовний, щоб можна було вільно погуляти по коридору, не перериваючи розмови по Skype, і просто насолоджуватися усіма плодами безперервної вафлі.
Для цих цілей вирішили взяти кілька Unifi тарілок з метою не морочитися з налаштуванням і щоб все працювало з коробки. По-крупному все так і було за одним АЛЕ, який і послужив причиною створення цього tutorial: контролер тарілок вміє працювати тільки через https, а так само до нього не покладається нормальної інструкції з проксированию через Nginx, существующая, м'яко кажучи, залишає бажати кращого, а так само не передбачає сценарій роботи з HTTP.

Необхідний рівень підготовки:

Будемо вважати, що ази Nginx відомі, куди поміщати конфіги і так зрозуміло, а сам веб сервер теж розгорнуто. Крім цього, мається на увазі, що контролер посуду вже налаштований. Якщо з цим виникають складнощі, то у Ubiquity є чудова інструкція для Linux і Windows. Але надалі будемо вважати, що ми всі тут пропалені користувачів linux.
Вся конфігурація перевірялася на Unifi Controller v5.2.9, Nginx v1.10.1, Debian Jessie, Java 8
І так, поїхали.

HTTP:

Все просто, потрібно лише покласти конфіг куди треба, але потрібні певні пояснення і попередження.
Всім, кому лінь думати читати, а просто треба, щоб все працювало, можна скопіювати конфіг і замінити в ньому server_name на відповідний, а так само адреса/порт в блоці upstream, якщо контролер розташований не в локалхосте:
upstream unifi {
server 127.0.0.1:8443;
}

server {
listen 80;
server_name unifi.domain.com;

error_log /var/log/unifi/nginx.log;
access_log /var/log/unifi/access.log;

proxy_ssl_verify off;
proxy_ssl_session_reuse on;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

proxy_cache off;
proxy_store off;

server_tokens off;

location / {
proxy_set_header Referer "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://unifi; 
proxy_redirect https:// http://;
header_filter_by_lua_block {
if ngx.header["Set-Cookie"] then 
ngx.header["Set-Cookie"] = { 
string.gsub(ngx.header["Set-Cookie"][1], "(.*)Secure;(.*)", "%1%2"),
string.gsub(ngx.header["Set-Cookie"][2], "(.*)Secure(.*)", "%1%2") 
}
end
}
}
}

Якщо Nginx зібраний з вихідних, то потрібно окремо встановити модуль ngx_http_lua_module.
Тепер можна перезавантажити Nginx:
sudo service nginx reload

Нюанси:
Так як контролер з коробки тільки підтримує HTTPS, то для його через проксі серверів HTTP нам доведеться модифікувати Cookie, відрізавши прапор secure, і в принципі відключити будь валідацію ssl upstream сервера. Спритні адміни кинуть в мене тапком, сказавши, що можна додати довірений сертифікат, попередньо прописавши його в контролер, але ми цей кейс розглядати не будемо на увазі його надмірної складності.
Тим не менш, не рекомендується тримати інфраструктурні речі на HTTP. Тільки якщо зовсім немає сертифіката, а хочеться, щоб контролер красиво стирчав назовні.
Можна поміняти слухає порт і будь-які інші установки за смаком.

HTTPS з дефолтними сертифікатом контролера:

Це лінивий варіант HTTPS. Контролер має свій ssl сертифікат з коробки, але його можна замінити на будь-який інший. І замість того, щоб його ретельно настроювати, ми просто попросимо Nginx погоджуватися на все.
Простими словами, весь трафік йде з інтернетів мережі по HTTPS до Nginx, а від Nginx до контролера вже незахищений. Якщо Unifi контролер і Nginx знаходяться в межах локалхоста або довіреної мережі, то це наш випадок:
upstream unifi {
server 127.0.0.1:8443;
}

# Редиректим на HTTPS
server {
listen 80;
server_name unifi.domain.com;
server_tokens off;
rewrite ^ https://$http_host$request_uri?;
}

server {
listen ssl 443;
server_name unifi.domain.com;

error_log /var/log/unifi/nginx.log;
access_log /var/log/unifi/access.log; 

ssl on;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
add_header Strict-Transport-Security "max-age=31536000" always;
server_tokens off;

proxy_ssl_verify off;
proxy_ssl_session_reuse on;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
proxy_cache off;
proxy_store off;

location / {
proxy_set_header Referer "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://unifi;
}
}

Додаткові налаштуванняМожна зробити перманентний редирект, замінивши
rewrite ^ https://$http_host$request_uri?;

на
rewrite ^ https://$http_host$request_uri? permanent;

Але краще цим займатися, коли ви переконалися в правильній роботі всієї системи.
У цьому конфіги треба замінити наступні параметри на свої:
  • Шлях до сертифіката ssl_certificate
  • Шлях до ключа сертифіката ssl_certificate_key
  • Ім'я сервера обох серверів(ssl і редирект) server_name
  • Порт і адресу upstream сервера при необхідності
І не забуваємо робити reload Nginx:
sudo service nginx reload

Ви можете запитати: "Але мен, чому в твоєму конфіги два сервера, хоча у мене він один?". Я відповім: один сервер приймає ssl трафік, проксируя його контролеру, а інший редиректит на перший, якщо до нас звернулися по HTTP, щоб не піддавати небезпеці наші діри безпеки.
А тепер залишилося саме солодке, справжніх параноїків серйозних адміністраторів.

HTTPS з кастомным сертифікатом контролера

Припустимо, що Nginx і контролер знаходяться тепер не довіреної мережі і ми не можемо бути на 100% впевнені в безпеці з'єднання між ними. В такому разі нам доведеться скористатися виданими ssl сертифікатом для нашого домену на якому буде знаходитися контролер, або створити свій.
Процедуру генерації self-signed сертифіката ми тут описувати не будемо, вона лише побічно стосується даного підручника. Вважаємо, що вже все готово і ми молодці.
І так, переконаємося, що у нас є на руках crt і key файли, вони нам потрібні, щоб підкласти наш сертифікат в Unifi контролер. Будемо вважати, що вони називаються unifi.crt і unifi.key відповідно.
Тепер нам потрібно згенерувати keystore файл для контролера. Такі команди потрібно виконувати в папці unifi.crt і unifi.key в корені. Не важливо, де лежить ця папка, нам потрібно в підсумку тільки фінальний файл:
openssl pkcs12 -export -in unifi.crt -inkey unifi.key -out unifi.p12

keytool -importkeystore -deststorepass aircontrolenterprise -destkeypass aircontrolenterprise -destkeystore keystore -srckeystore unifi.p12 -srcstoretype PKCS12 -srcstorepass aircontrolenterprise

Тепер беремо отриманий keystore і переміщаємо його в папку data докорінно контролера. Дефолтний розташування кореневої папки: /usr/lib/unifi. Файл у підсумку повинен виявитися по наступному шляху: /usr/lib/unifi/data/keystore
P12 документик нам не потрібно, його можна видалити або залишити на пам'ять, поставивши в рамочку.
Тепер рестартим сервіс Unifi:
sudo service unifi restart

З контролером ніяких маніпуляцій більше не потрібно, тепер справа за Nginx. Наш конфіг буде мало відрізнятися від попереднього варіанту, за винятком факту, що ми вже не будемо сліпо приймати будь сертифікат. Якщо сертифікат self-signed, то вкажемо Nginx довіряти йому.
Випадок для виданого сертифіката
Конфіг Nginx:
upstream unifi {
server 127.0.0.1:8443;
}

server {
listen 80;
server_name unifi.domain.com;
server_tokens off;
rewrite ^ https://$http_host$request_uri?;
}

server {
listen ssl 443;
server_name unifi.domain.com;

error_log /var/log/unifi/nginx.log;
access_log /var/log/unifi/access.log; 

ssl on;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
add_header Strict-Transport-Security "max-age=31536000" always;
server_tokens off;

proxy_ssl_session_reuse on;

location / {
proxy_set_header Referer "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://unifi;
}
}

Повторюся, що потрібно замінити наступні параметри конфига:
  • Шлях до сертифіката ssl_certificate
  • Шлях до ключа сертифіката ssl_certificate_key
  • Ім'я сервера обох серверів(ssl і редирект) server_name
  • Порт і адресу upstream сервера при необхідності
Тепер self-signed сертифікат:
Нам потрібні два вже знайомих файлу з минулих кроків: unifi.crt і unifi.key. Для виданого сертифіката вони нам не потрібні, так як Nginx розумний і вміє валідувати їх в бюро сертифкации. Тут же нам доведеться йому явно їх вказати.
Конфіг Nginx:
upstream unifi {
server 127.0.0.1:8443;
}

server {
listen 80;
server_name unifi.domain.com;
server_tokens off;
rewrite ^ https://$http_host$request_uri?;
}

server {
listen ssl 443;
server_name unifi.domain.com;

error_log /var/log/unifi/nginx.log;
access_log /var/log/unifi/access.log; 

ssl on;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
add_header Strict-Transport-Security "max-age=31536000" always;
server_tokens off;

proxy_ssl_verify on;
proxy_ssl_certificate /etc/nginx/ssl/unifi.crt;
proxy_ssl_certificate_key /etc/nginx/ssl/unifi.key;
proxy_ssl_trusted_certificate /etc/nginx/ssl/unifi.crt;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
proxy_ssl_session_reuse on;

location / {
proxy_set_header Referer "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://unifi;
}
}

Як і вище, не забуваємо замінювати параметри конфига на свої:
  • Шлях до сертифіката ssl_certificate
  • Шлях до ключа сертифіката ssl_certificate_key
  • Ім'я сервера обох серверів(ssl і редирект) server_name
  • Порт і адресу upstream сервера при необхідності
    , А також
  • Шлях до unifi.crt і unifi.key файлів (їх можна покласти куди завгодно. Я б рекомендував зробити окрему папку в корені Nginx, щоб нічого не загубилося)
Тепер можна перезавантажити Nginx:
sudo service nginx reload



Ось і все, ми домоглися бажаного. Наш контролер тепер доступний за вказаною адресою.
Картинка з результатомimage
Буду радий відповісти на будь-які питання і прийняти зворотний зв'язок.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.