📜 ⬆️ ⬇️

Unifi Controller + Nginx. HTTP & HTTPS

image


Brief essence:


Step-by-step instructions on proxying a Unifi controller through Nginx via http or https.


Configs, clear examples, comments.


Prologue :


Our company is developing mobile applications, and as you might guess, there are a lot of different devices in the office, they all love Wi-Fi and not just Wi-Fi, but seamless so that you can walk freely along the corridor without interrupting conversations on Skype and just enjoy all the fruits of uninterrupted waffles.


For these purposes, we decided to take a few Unifi plates in order to not bother with the setting and that everything worked out of the box. On a large scale, everything was as it was for one BUT, which caused the creation of this tutorial: the dish controller can work only via https, and the normal instructions for proxying through Nginx, existing to put it mildly, leaves much to be desired, as well. as well as does not provide a script to work with HTTP.


Required level of training:


We assume that the basics of Nginx are known, where to put configs is understandable, and the web server itself is also deployed. In addition, it is assumed that the dish controller is already configured. If there are difficulties with this, then Ubiquity has an excellent instruction for Linux and Windows . But in the future we will assume that we are all hardened linuxids here.


The entire configuration was tested on Unifi Controller v5.2.9, Nginx v1.10.1, Debian Jessie, Java 8


And so, let's go.


Http:


It's simple, you just need to put the config where necessary, but will require certain explanations and warnings.


Anyone lazy think read, but just need to make everything work, you can copy the config and replace server_name with the appropriate one, as well as the address / port in the upstream block, if the controller is not located in the local host:


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 } } } 

If Nginx is built from source, then you need to separately install the ngx_http_lua_module module.


Now you can reboot Nginx:


 sudo service nginx reload 

Nuances:
Since the controller out of the box only supports HTTPS, then for its proxying through HTTP we will have to modify the Cookie, cut off the secure flag, and in principle disable any validation of the ssl upstream server. Smart administrators will throw a slipper at me, saying that you can add a trusted certificate by pre-registering it to the controller, but we will not consider this case because of its excessive complexity.


However, it is not recommended to keep the infrastructure stuff on HTTP. Only if there is no certificate at all, but I want the controller to stick out beautifully.


You can change the listening port and any other settings to taste.


HTTPS with default controller certificate:


This is the lazy version of https. The controller has its ssl certificate out of the box, but it can be replaced with any other. And instead of meticulously tweaking it, we simply ask Nginx to agree to everything.


In simple terms, all traffic comes from internet networks over HTTPS to Nginx, and from Nginx to the controller is already unprotected. If the Unifi controller and Nginx are within a localhost or trusted network, then this is our case:


 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 443 ssl; 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; } } 

Additional settings

You can make a permanent redirect, replacing


 rewrite ^ https://$http_host$request_uri?; 

on


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

But it is better to do this when you are convinced of the correct operation of the entire system.


In this config, you need to replace the following parameters with your own:



And do not forget to reload Nginx:


 sudo service nginx reload 

You may ask: "But Maine, why are there two servers in your config, although I have one?". I will answer: one server accepts ssl traffic, proxying it to the controller, and the other redirects to the first one if we are contacted via HTTP in order not to endanger our security holes.


And now there is the sweetest, for real paranoids serious administrators.


HTTPS with a custom controller certificate


Suppose that Nginx and the controller are no longer in a trusted network and we cannot be 100% sure that the connection between them is secure. In this case, we will have to use the certificate issued by ssl for our domain on which the controller will be located, or generate our own.


We will not describe the procedure for generating a self signed certificate here, it only indirectly concerns this tutorial. We believe that everything is ready and we are great.


And so, let's make sure that we have crt and key files in our hands, we will need them to put our certificate into the Unifi controller. We assume that they are called unifi.crt and unifi.key respectively.


Now we need to generate the keystore file for the controller. The following commands need to be executed in the folder with unifi.crt and unifi.key at the root. No matter where this folder is located, we will only need the final file as a result:


 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 

Now we take the keystore and move it to the data folder in the root of the controller. The default root folder location is / usr / lib / unifi . The file should end up in the following path: / usr / lib / unifi / data / keystore


We will not need P12 documentation, you can delete it or leave it for memory by putting it in a frame.


Now restart service Unifi:


 sudo service unifi restart 

With the controller, no more manipulations will be required, now it's up to Nginx. Our config will differ little from the previous version, except for the fact that we will no longer blindly accept any certificate. If the self certificate is signed, then we will tell Nginx to trust it.


Case for issued certificate


Nginx config:


 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 443 ssl; 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; } } 

I repeat that you need to replace the following config parameters:



Now self signed certificate:


We will need two already familiar files from the previous steps: unifi.crt and unifi.key . We did not need them for the issued certificate, since Nginx is clever and can validate them in the certification bureau. Here we will have to specify them explicitly.


Nginx config:


 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 443 ssl; 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; } } 

As above, we do not forget to replace the config parameters with our own:



Now you can reboot Nginx:


 sudo service nginx reload 



That's all, we have achieved the desired. Our controller is now available at the specified address.


Picture with the result

image


I will be glad to answer any questions and accept feedback.


PS After reading the comments, I want to thank all the respondents, it is nice to read your feedback.
I will make a mini-faq of the most popular questions:


1. Why Nginx, but not% software_name%?
Answer: The company used Nginx, it was necessary to solve the problem through it.


2. How is the article related to Unifi? This is% common_techonology_name%!
Answer: The goal was to write a narrow tutorial specifically for Unifi + Nginx, since not everyone who has difficulty with its configuration can clearly formulate the technology stack they need.


')

Source: https://habr.com/ru/post/316786/


All Articles