Table_of_Contents
1.1 Primary Domain versus Virtual Domains
1.2 SubDomain versus SubDirectory Addressing
1.3 Server Domain Configuration
1.4 SubDomain Service Configuration
1.5 SubDirectory Service Configuration
1.6 Location Blocks
1.6.1 Directory Locations
1.6.2 Proxy Locations
1.7 SecureOffice Nginx Configuration
1.7.1 Primary Domain Configuration
1.7.2 Subdomain Configuration
List of Figures
Figure 1: Nginx Server Configuration
Figure 2: Directory Location
Figure 3: Proxy Location
Figure 4: Main Nginx Configuration
Figure 5: LetsEncrypt Location Support
Figure 6: Logfile Location Support
Figure 7: Domain Vhost Block
Figure 8: SubDomain Vhost Block
The SecureOffice / OpenWrt Nginx webserver behaves and is configured the same as standard Nginx. Consult the Nginx user guide, Nginx Wiki and Nginx examples for further information.
By default (new installation) Nginx is installed and configured to serve the OpenWrt GUI when addressed (from a client on LAN) at http(s)//<LAN Address>. A Nginx test page can be accessed at http(s)//<LAN Address>/nginx.html.
By default, Nginx is configured to block any access when addressed by clients not connected to the SecureOffice LAN (cable or WiFi).
By default. Nginx is configured to upgrade any http (port 80) request to https (port 443) using self-signed SSL certificates.
Users familiar with Nginx can inspect "/etc/nginx/nginx.conf" and the files in "/etc/nginx/locations" and "/etc/nginx/vhosts" to understand how web services are integrated with SecureOffice / OpenWrt.
The primary domain is the domain (<your domain>) that SecureOffice was initially configured for (pre-requisite). The primary domain (without www) is also set in "/etc/hosts".
The primary domain is what Nginx is configured to serve at location "/" when addressed by http(s)//<your domain> or https://www.<your domain> where <your domain> is the first entry in SSL certificates.
Additional domains (different from primary domain) are whatever Nginx is configured to serve at alternate domain names. For example, if your primary domain is "example.com", you can have another domain named "KilroyWasHere.com". Additional domains are usually configured as aliases using your DDNS provider. Internet search "your DDNS provider alias" to configure alternate domains (multiple sites) different from your primary domain.
Virtual hosts (domain names) are configured using Nginx "server" directives.
The following sections are applicable for services running at the primary and additional virtual domains.
When considering adding a web service (site) to SecureOffice, the first thing to consider is the form of the URL(s) used for site access.
SubDomain addressing has URL's (addresses) of the form http(s)//subdomain.<your domain> (example: http(s)//MyWeatherStation/example.com) and is the least complex to configure.
SubDirectory addressing has URL's of the form http(s)//<your domain>/subdirectory (example: http(s)//example.com/MyWeatherStation) and is usually more complex to configure.
SubDomain addressing has the following pro's / cons:
SubDirectory addressing has the following pro's / cons:
Independent of subdomain / subdirectory addressing scheme, Nginx must be configured with a server (vhost) block to serve the domain. Any file named *.conf in directory "/etc/nginx/vhosts/" will be included in Nginx configuration. It is recommended that each domain or subdomain have its own <domain name>.conf file in directory "/etc/nginx/vhosts/".
A template vhost / domain configuration file (/etc/nginx/vhosts/example.conf) provided by SecureOffice is shown below:
# Example Nginx configuration for site example.com
# Change example.com to your site DNS <your domain> name
# If using any functions such as non-wildcard LetsEncrypt SSL certificates, private internet access only, or CGI / php, uncomment (remove ##) at beginning of all lines between function Start and End comments
# If not using a function, all double comment (##) lines pertaining to it can be deleted
# Uncomment (remove single #) at beginning of each line below
# This will serve a Nginx test page accessible at https://<your domain> or https://<your domain>
#server {
# listen 80;
# listen [::]:80;
# server_name example.com;
## # Start location required if using LetsEncrypt non-wildcard SSL certificates
## location /.well-known/acme-challenge/ {
## default_type "text/plain";
## alias /www/.well-known/acme-challenge/;
## break;
## }
## # End location required if using LetsEncrypt non-wildcard SSL certificates
# location / {
# # Permanently redirect to https
# return 301 https://$host$request_uri;
# }
#}
#server {
# listen 443;
# listen [::]:443;
# server_name example.com www.example.com;
# # Note: SSL settings are inherited from main configuration: /etc/nginx/nginx.conf for all vhosts
# client_body_timeout 10;
# client_header_timeout 10;
# send_timeout 60; # 60 sec should be enough, if experiencing a lot of timeouts, increase this.
# output_buffers 1 32k;
# postpone_output 1460;
## # Start Parameters required for serving CGI / php
## fastcgi_connect_timeout 300;
## fastcgi_send_timeout 300;
## fastcgi_read_timeout 300;
## fastcgi_buffer_size 32k;
## fastcgi_buffers 4 32k;
## fastcgi_busy_buffers_size 32k;
## fastcgi_temp_file_write_size 32k;
## # End parameters required for serving CGI / php
## # Start restrict internet access to private (LAN access only) for entire domain
## allow 192.168.0.0/16;
## allow 172.16.0.0/12;
## allow 10.0.0.0/8;
## allow 127.0.0.0/8;
## deny all;
## # End restrict internet access to private (LAN access only) for entire domain
# location / {
## # Start restrict internet access to private (LAN access only) for this location only
## allow 192.168.0.0/16;
## allow 172.16.0.0/12;
## allow 10.0.0.0/8;
## allow 127.0.0.0/8;
## deny all;
## # End restrict internet access to private (LAN access only) for this location only
# index nginx.html;
# }
## # Location required for serving CGI / php
## location ~ \.php$ {
## fastcgi_index index.php;
## include fastcgi_params;
## fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
## if (-f $request_filename) {
## # Only throw it at PHP-FPM if the file exists (prevents some PHP exploits)
## fastcgi_pass unix:/var/run/php7-fpm.sock;
## }
## }
## # End location required for serving CGI / php
#}
Figure 1:Nginx Server Configuration
Copy the template file "/etc/nginx/vhosts/example.conf" to "/etc/nginx/vhosts/<yourdomain>.conf" and alter to taste:
Services will be addressed by subdomain as http(s)://<subdomain>.<yourdomain> (for example http(s)//MyWeatherStation.example.com).
Each subdomain service requires an additional server entry as above, replacing "example.com www.example.com" by "<subdomain>.<your domain>". Location blocks must be added, with contents dependent on the service(s) you are providing.
Services will be addressed by subdirectory as http(s)://<yourdomain>.<subdirectory> (for example http(s)//example.com/MyWeatherStation). Location blocks must be added for each possible sub URL.
Location blocks are used to instruct Nginx what to do with sub addresses, the portion of the URL following the base URL (example.com). For example, with a URL of example.com/Files, the location is "/Files".
Referring to Figure 1, location blocks (may be more than one) replace the existing location block.
Public internet access (via WAN) can be allowed / denied for any server or location as discussed in the next section.
Location blocks are where service specific Nginx directives such as rewrite, access control and proxying are done. When considering adding a new service or website to SecureOffice, normally the service / website documentation contains requirements. If that is inadequate, internet search "Nginx proxy <service name>".
Directory locations are used to serve content (files) residing on the SecureOffice filesystem. An example location block which serves the contents of a directory is shown below.
location /Files/ {
default_type "text/plain";
autoindex on;
alias /etc/Files/;
# Comment "#" or remove following lines to allow internet access
# for location
allow 192.168.0.0/16;
allow 172.16.0.0/12;
allow 10.0.0.0/8;
allow 127.0.0.0/8;
deny all;
End comment lines
# uncomment following line to allow internet access for this
# particular location if access blocked in containing server block
# allow all;
}
Figure 2:Directory Location
A URL of "https://example.com/Files" will display a directory list of "/etc/Files". A URL of "https://example.com/Files/filename" will display the contents of filename. Note that the location alias may be a complete website, in which case remove the "autoindex" directive and add CGI / php support (if required) to the server and location blocks as shown in Figure 1.
Public internet access (via WAN) can be allowed by commenting or omitting the allow and deny directives.
Proxy locations are used to serve (proxy) the contents of another server at the location. The server may be local (at an alternate port on SecureOffice or remote on another IP address / port).
location / {
# Comment "#" following lines to allow internet access
allow 192.168.0.0/16;
allow 172.16.0.0/12;
allow 10.0.0.0/8;
allow 127.0.0.0/8;
deny all;
# End comment lines
# $remote_addr is the callers IP address
# $server_port is the listening port of containing server block
proxy_set_header Host www.example.com:$server_port;
# Allow downstream sites to know who's connecting
proxy_set_header X-Forwarded-For $remote_addr;
# proxy server running http / https at 192.168.10.250, same port #
# proxy_pass $scheme://192.168.10.250:$server_port;
# proxy server running http at 192.168.10.250, alternate <port number>
# proxy_pass http://192.168.10.250:<port number>;
# proxy server running http on SecureOffice, alternate <port number>
# proxy_pass http://127.0.0.1:<port number>;
}
Figure 3:Proxy Location
The proxy_pass IP address (or DNS name) and port in the above example can be for any webserver internal or external to SecureOffice. For example, this website is running on a Sme-Server virtual machine (Vmware) hosted by SecureOffice.
For reference, the main SecureOffice Nginx configuration file (/etc/nginx/nginx.conf) is shown below:
# Note: external servers (vhosts) should not redirect http to https, else redirect loop (eg: sme-server)
user root;
worker_processes auto;
pid /var/run/nginx.pid;
events {}
http {
access_log off;
log_format openwrt
'$request_method $scheme://$host$request_uri => $status'
' (${body_bytes_sent}B in ${request_time}s) <- $http_referer';
include mime.types;
default_type application/octet-stream;
sendfile on;
client_max_body_size 128M;
large_client_header_buffers 2 1k;
gzip on;
gzip_vary on;
gzip_proxied any;
root /www;
server {
listen [::]:80 default_server;
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name localhost;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:DHE+AESGCM:DHE:!RSA!aNULL:!eNULL:!LOW:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!CAMELLIA:!SEED";
ssl_session_tickets off;
ssl_certificate /etc/ssl/domains/domain.crt;
ssl_certificate_key /etc/ssl/domains/domain.key;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 32k;
fastcgi_buffers 4 32k;
fastcgi_busy_buffers_size 32k;
fastcgi_temp_file_write_size 32k;
client_body_timeout 10;
client_header_timeout 10;
send_timeout 60; # 60 sec should be enough, if experiencing a lot of timeouts, increase this.
output_buffers 1 32k;
postpone_output 1460;
# Allow only private IP addresses
allow 192.168.0.0/16;
allow 172.16.0.0/12;
allow 10.0.0.0/8;
allow 127.0.0.0/8;
deny all;
location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
}
location /cgi-bin/luci {
index index.html;
include uwsgi_params;
uwsgi_param SERVER_ADDR $server_addr;
uwsgi_modifier1 9;
uwsgi_pass unix:////var/run/luci-webui.socket;
}
location ~ /cgi-bin/cgi-(backup|download|upload|exec) {
include uwsgi_params;
uwsgi_param SERVER_ADDR $server_addr;
uwsgi_modifier1 9;
uwsgi_pass unix:////var/run/luci-cgi_io.socket;
}
location /luci-static {
error_log stderr crit;
}
location /ubus {
ubus_interpreter;
ubus_socket_path /var/run/ubus.sock;
ubus_parallel_req 2;
} location ~ \.php$ {
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
if (-f $request_filename) {
# Only throw it at PHP-FPM if the file exists (prevents some PHP exploits)
fastcgi_pass unix:/var/run/php7-fpm.sock;
}
}
include locations/*.conf;
}
include vhosts/*.conf;
}
Figure 4:Main Nginx Configuration
This file configures Nginx operation to serve the OpenWrt GUI, SSL, php and fastcgi. The "include locations/*.conf;" directive instructs Nginx to serve additional content using any config files found in directory "/etc/nginx/locations".
An example location block which is served by "default_server" is file "/etc/nginx/locations/acme.conf" (to handle the case of "default_server" being changed to a real domain if, for some reason it is desired (unwise) for portions of the OpenWrt GUI to be publicly accessible). This configuration provides LetsEncrypt support for this use case:
location /.well-known/acme-challenge/ {
default_type "text/plain";
allow all;
alias /var/letsencrypt/;
}
Figure 5:LetsEncrypt Location Support
Another example location block which is served by "default_server" is file "/etc/nginx/locations/vtprotect.conf" used to display a License status logfile in the OpenWrt GUI (System->Licensing->Manage):
location /vtdaemon.txt {
alias /tmp/log/vtdaemon.log;
}
Figure 6:Logfile Location Support
The main Nginx configuration file (Figure 4), has an "include vhosts/*.conf;" directive which instructs Nginx to serve additional content using any config files found in directory "/etc/nginx/vhosts". This allows additional servers to be defined, with self-contained configuration.
An example Nginx vhost (domain) conf file with a public site (example.com) based on "example.conf" is shown below:
# Example Nginx configuration for site example.com
# Change example.com to your site DNS (domain) name
# If not using wildcard SSL certificates, uncomment (remove ##) at beginning of each line below
# If using wildcard SSL certificates, lines starting with ## can be omitted.
# Uncomment (remove #) at beginning of each line below
# This will serve a Nginx test page accessible at https://example.com or https://www.example.com
#server {
listen 80;
listen [::]:80;
server_name example.com;
## location /.well-known/acme-challenge/ {
## default_type "text/plain";
## alias /www/.well-known/acme-challenge/;
## break;
## }
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443;
listen [::]:443;
server_name example.com www.example.com;
# Note: SSL settings are inherited from main configuration: /etc/nginx/nginx.conf for all vhosts
client_body_timeout 10;
client_header_timeout 10;
send_timeout 60; # 60 sec should be enough, if experiencing a lot of timeouts, increase this.
output_buffers 1 32k;
postpone_output 1460;
# Comment "#" following lines to allow internet access
# for entire virtual host (domain)
#allow 192.168.0.0/16;
#allow 172.16.0.0/12;
#allow 10.0.0.0/8;
#allow 127.0.0.0/8;
#deny all;
#End comment lines
location / {
index nginx.html;
}
}
Figure 7:Domain Vhost Block
In the above config file, the server block redirects port 80 (http) to port 443 (https) and optionally handles LetsEncrypt SSL site verification requests. A Nginx test page is available at https://<your domain> or https://www.<your domain>.
All Nginx domain configuration will be as above, differing only by the contents of the "location" block which determines what content is to be served. In the example above, static file "nginx.html" is served from the default web root directory of "/www/". The location block may refer to directory or proxy locations as discussed previously.
Some SecureOffice packages such as SecurePBX (Freeswitch / Fusionpbx), Zoneminder, docker-hassio (Home Assistant), docker-nextcloud and luci-app-rclone install Nginx configuration files to directory "/etc/nginx/vhosts/" allowing their web GUI's to be available as subdomains (https://<package subdomain name>.<your domain> and integrated with the OpenWrt menu system. Refer to package documentation for details which can also be used as examples for adding custom services.
An example Nginx vhost (subdomain) conf file for a subdomain called "some_service" of domain "your_domain" is shown below:
server {
listen 443;
listen [::]:443;
#server_name <some_service>.<your_domain>;
#add_header X-Frame-Options "ALLOW-FROM https://<your LAN address>/ https://$server_name/";
#add_header Content-Security-Policy "frame-ancestors 'self' https://<your LAN address> https://$server_name/";
server_name <some_service>.<your_domain>;
add_header X-Frame-Options "ALLOW-FROM https://<Your LAN address>/ https://$server_name/";
add_header Content-Security-Policy "frame-ancestors 'self' https://<Your LAN Address> https://$server_name/";
location / {
# Comment "#" following lines to allow internet access
# Otherwise, <some_service> only accessable from local LAN
allow 192.168.0.0/16;
allow 172.16.0.0/12;
allow 10.0.0.0/8;
allow 127.0.0.0/8;
deny all;
# End lines to comment
# Set all cookies to secure, httponly and samesite (strict, lax or none)
# Need Nginx 1.19.3+ for proxy_cookie_flags
proxy_cookie_flags ~ secure httponly samesite=none;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_pass http://<LAN address of service>:<service port>;
proxy_set_header Host $host;
proxy_redirect http:// https://;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Figure 8:SubDomain Vhost Block
Assuming Nginx has been configured for your primary domain (previous section), the above Vhost configuration will allow you to make any arbitrary server at any port on your LAN (including external to SecureOffice devices) as a subdomain of your primary domain. This is the general approach used for SecureOffice and subdomains.
If the "allow", "deny" lines in the above configuration are not commented (no leading "#"), the service will be private, restricted to clients on your local LAN or using secure remote access methods.
If the "allow", "deny" lines in the above configuration are commented (leading "#"), the service will be public, available to all. Ensure that the service has adequate authentication to deter hackers.
|
Technologies Used: