nginx_modsite command for NGINX

Using nginx_modsite command similar for use a2ensite and a2dissite with NGINX

nginx_modsite command for NGINX

As we all know, we can enable or disable a website using Apache on Debian and Ubuntu Linux. We remembered and appreciated using the a2ensite and a2dissite commands, why not for NGINX!

Unfortunately, there is no corresponding standard command in NGINX, but there is a workaround using a2ensite and a2dissite for NGINX.

Of course, the following command can create the symlink to the website configuration file:

$ sudo ln -s /etc/nginx/sites-available/example.org /etc/nginx/sites-enabled/

As well as we can unlink the site from enabled sites:

$ sudo unlink /etc/nginx/sites-enabled/example.org

nginx_modsite command for NGINX

The nginx_modsite command for use enable and disablbe NGINX websites and also list them.

Easy to use nginx_modsite

Just create this script file /usr/bin/nginx_modsite.

#!/bin/bash

##
#  File:
#    nginx_modsite
#  Description:
#    Provides a basic script to automate enabling and disabling websites found
#    in the default configuration directories:
#      /etc/nginx/sites-available and /etc/nginx/sites-enabled
#    For easy access to this script, copy it into the directory:
#      /usr/local/sbin
#    Run this script without any arguments or with -h or --help to see a basic
#    help dialog displaying all options.
##

# Copyright (C) 2010 Michael Lustfield <mtecknology@ubuntu.com>

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.

##
# Default Settings
##

NGINX_CONF_FILE="$(awk -F= -v RS=' ' '/conf-path/ {print $2}' <<< $(nginx -V 2>&1))"
NGINX_CONF_DIR="${NGINX_CONF_FILE%/*}"
NGINX_SITES_AVAILABLE="$NGINX_CONF_DIR/sites-available"
NGINX_SITES_ENABLED="$NGINX_CONF_DIR/sites-enabled"
SELECTED_SITE="$2"

##
# Script Functions
##

ngx_enable_site() {
    [[ ! "$SELECTED_SITE" ]] &&
        ngx_select_site "not_enabled"

    [[ ! -e "$NGINX_SITES_AVAILABLE/$SELECTED_SITE" ]] && 
        ngx_error "Site does not appear to exist."
    [[ -e "$NGINX_SITES_ENABLED/$SELECTED_SITE" ]] &&
        ngx_error "Site appears to already be enabled"

    ln -sf "$NGINX_SITES_AVAILABLE/$SELECTED_SITE" -T "$NGINX_SITES_ENABLED/$SELECTED_SITE"
    ngx_reload
}

ngx_disable_site() {
    [[ ! "$SELECTED_SITE" ]] &&
        ngx_select_site "is_enabled"

    [[ ! -e "$NGINX_SITES_AVAILABLE/$SELECTED_SITE" ]] &&
        ngx_error "Site does not appear to be \'available\'. - Not Removing"
    [[ ! -e "$NGINX_SITES_ENABLED/$SELECTED_SITE" ]] &&
        ngx_error "Site does not appear to be enabled."

    rm -f "$NGINX_SITES_ENABLED/$SELECTED_SITE"
    ngx_reload
}

ngx_list_site() {
    echo "Available sites:"
    ngx_sites "available"
    echo "Enabled Sites"
    ngx_sites "enabled"
}

##
# Helper Functions
##

ngx_select_site() {
    sites_avail=($NGINX_SITES_AVAILABLE/*)
    sa="${sites_avail[@]##*/}"
    sites_en=($NGINX_SITES_ENABLED/*)
    se="${sites_en[@]##*/}"

    case "$1" in
        not_enabled) sites=$(comm -13 <(printf "%s\n" $se) <(printf "%s\n" $sa));;
        is_enabled) sites=$(comm -12 <(printf "%s\n" $se) <(printf "%s\n" $sa));;
    esac

    ngx_prompt "$sites"
}

ngx_prompt() {
    sites=($1)
    i=0

    echo "SELECT A WEBSITE:"
    for site in ${sites[@]}; do
        echo -e "$i:\t${sites[$i]}"
        ((i++))
    done

    read -p "Enter number for website: " i
    SELECTED_SITE="${sites[$i]}"
}

ngx_sites() {
    case "$1" in
        available) dir="$NGINX_SITES_AVAILABLE";;
        enabled) dir="$NGINX_SITES_ENABLED";;
    esac

    for file in $dir/*; do
        echo -e "\t${file#*$dir/}"
    done
}

ngx_reload() {
    read -p "Would you like to reload the Nginx configuration now? (Y/n) " reload
    [[ "$reload" != "n" && "$reload" != "N" ]] && invoke-rc.d nginx reload
}

ngx_error() {
    echo -e "${0##*/}: ERROR: $1"
    [[ "$2" ]] && ngx_help
    exit 1
}

ngx_help() {
    echo "Usage: ${0##*/} [options]"
    echo "Options:"
    echo -e "\t<-e|--enable> <site>\tEnable site"
    echo -e "\t<-d|--disable> <site>\tDisable site"
    echo -e "\t<-l|--list>\t\tList sites"
    echo -e "\t<-h|--help>\t\tDisplay help"
    echo -e "\n\tIf <site> is left out a selection of options will be presented."
    echo -e "\tIt is assumed you are using the default sites-enabled and"
    echo -e "\tsites-disabled located at $NGINX_CONF_DIR."
}

##
# Core Piece
##

case "$1" in
    -e|--enable)    ngx_enable_site;;
    -d|--disable)   ngx_disable_site;;
    -l|--list)  ngx_list_site;;
    -h|--help)  ngx_help;;
    *)      ngx_error "No Options Selected" 1; ngx_help;;
esac

Make the script executable with ran chmod 700 /usr/bin/nginx_modsite.

Using the command nginx_modsite

To list all available virtualhosts, you can run the following command.

$ sudo nginx_modsite -l

Enable virtualhost “example.org”.

$ sudo nginx_modsite -e example.org

Disable virtualhost “example.org”.

$ sudo nginx_modsite -d example.org

About NGINX

Nginx “engine x” is an open source web server that can also be used as a reverse proxy, load balancer, mail proxy and HTTP cache. The software was created by Russian developer Igor Sysoev and publicly released in 2004. Nginx is free and open-source software, released under the terms of the 2-clause BSD license. A large fraction of web servers use Nginx, often as a load balancer.

Nginx is built to offer low memory usage and high concurrency. Rather than creating new processes for each web request, Nginx uses an asynchronous, event-driven approach where requests are handled in a single thread.

With Nginx, one master process can control multiple worker processes. The master maintains the worker processes, while the workers do the actual processing. Because Nginx is asynchronous, each request can be executed by the worker concurrently without blocking other requests.

Nginx vs Apache Usage Stats

Apache is another popular open source web server. In terms of raw numbers, Apache is the most popular web server in existence and is used by 43.6% (down from 47% in 2018) of all websites with a known web server, according to W3Techs. Nginx comes in a close second at 41.8%.

Netcraft ran a survey across 233 million domains and found Apache usage at 31.54% and Nginx usage at 26.20%.

CSP Header Reverse Proxy Whitepaper

When delivering the HTML document, a special HTTP CSP Header is required that allows the browser to apply the content security policy, which we want to check here in this Whitepaper using a nginx reverse proxy.

Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks.

These attacks are used for everything from data theft, to site defacement, to malware distribution. This CSP header configuration is highly secure, but it is recommended to test it first to ensure that it does not block third party scripts. Scan Security Headers is an excellent tool to analyze your CSP and HSTS response headers configuration.

There are several versions: CSP (deprecated), CSP2 (current), CSP3 (under development). As of: 2022

Check delivered CSP Headers values

In this Whitepaper we check the CSP header delivered from reverse proxy values in the Chrome browser with hit the F12 key, navigate to the Network tab then under Headers view Response Headers.

CSP-Header Reverse Proxy Whitepaper

  when the chrome developer tools are open, you first have to reload the page, then select any element in the name column so that the response headers appear on the right pane.

Check Content Security Policy (CSP) Headers

Content Security Policy (CSP) comes with a whole range of parameters that can be used to fine-tune browser behavior.

You can use the online tool securityheaders.io to check the security headers of a website or your own web server. The rating is modeled on SSLLabs – a service for examining the TLS settings of web servers. Alternatively try serpworx.com to analyze CSP header and HSTS response header of your website or your reverse proxy.

X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised in the Content-Type headers should be followed and not be changed. The header allows you to avoid MIME type sniffing by saying that the MIME types are deliberately configured.

HTTP Strict-Transport-Security configuration

HTTP Strict-Transport-Security response header (often abbreviated as HSTS) informs browsers that the site should only be accessed using HTTPS. That any future attempts to access it using HTTP should automatically be converted to HTTPS.

add_header Content-Security-Policy "default-src https: 'self'; script-src https: 'self'; style-src https: 'self'; img-src *; frame-src 'self'; connect-src https: 'self';";
add_header X-Content-Type-Options nosniff;
add_header Content-Security-Policy "object-src 'none'; base-uri 'none'; require-trusted-types-for 'script'; frame-ancestors 'self';";
add_header Strict-Transport-Security "max-age=15552001; includeSubdomains; preload";

Check CSP Header and HSTS response Header

If you can configure your own web server or reverse proxy, then there are these settings options.

add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options nosniff;
add_header Strict-Transport-Security "max-age=31536000";

CSP Header Reverse Proxy configuration

The configuration file using nginx as a reverse proxy can look like this.

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  server_name example.domain.com;
  ssl_certificate /etc/nginx/ssl/ca.crt;
  ssl_certificate_key /etc/nginx/ssl/cert.key;

  # Only return Nginx in server header
  server_tokens off;

  ssl_dhparam /etc/ssl/certs/dhparam.pem;

  ssl_protocols TLSv1.2 TLSv1.3;
  # Compilation of the top cipher suites 2024
  # https://ssl-config.mozilla.org/#server=nginx
  ssl_ciphers ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-CCM:DHE-RSA-AES256-CCM8:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-CCM:DHE-RSA-AES128-CCM8:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256;

  # Perfect Forward Secrecy(PFS) is frequently compromised without this
  ssl_prefer_server_ciphers on;

  ssl_session_tickets off;
  # Enable SSL session caching for improved performance
  ssl_session_timeout 1d;
  ssl_session_cache shared:SSL:10m;
  # By default, the buffer size is 16k, which corresponds to minimal overhead when sending big responses.
  # To minimize Time To First Byte it may be beneficial to use smaller values
  ssl_buffer_size 8k;

  # OCSP stapling
  ssl_stapling on;
  ssl_stapling_verify on;

  # Security headers
  add_header X-Content-Type-Options nosniff;
  ## Content-Security-Policy (CSP): Yes
  ## No 'script-src' directive, you need to test it yourself
  add_header Content-Security-Policy "object-src 'none'; base-uri 'none'; require-trusted-types-for 'script'; frame-ancestors 'self';";
  ## The safest CSP, only block your website to be inside an inframe
  # add_header Content-Security-Policy "frame-ancestors 'self';";
  ## Strict Transport Security (HSTS): Yes
  add_header Strict-Transport-Security "max-age=15552001; includeSubdomains; preload";

 location / {
        proxy_pass http://203.0.113.10:80/;
        include proxy_params;
    }

}

You can implement CSP in Apache by adding the following entry in /etc/apache2/sites-available/example.domain.conf or into your .htaccess file:

<IfModule mod_headers.c>
        Header set X-XSS-Protection "1; mode=block"
        Header set X-Frame-Options "sameorigin"
        Header set X-Content-Type-Options "nosniff"
        Header set X-Permitted-Cross-Domain-Policies "none"
        Header set Content-Security-Policy "upgrade-insecure-requests;"
        Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        Header set Feature-Policy "camera 'none'; fullscreen 'self'; geolocation *; microphone 'self' https://example.domain.com/*"
        Header always set Permissions-Policy "accelerometer=(),autoplay=(),camera=(),cross-origin-isolated=(),display-capture=(self),encrypted-media=(),fullscreen=*,geolocation=(self),gyroscope=(),keyboard-map=(),magnetometer=(),microphone=(),midi=(),payment=*,picture-in-picture=(),publickey-credentials-get=(),screen-wake-lock=(),sync-xhr=(),usb=(),xr-spatial-tracking=(),gamepad=(),serial=()"
<IfModule mod_headers.c>

Check whether the Apache headers module is enabled, if not already done execute these commands. Check Your Security Headers here.

$ a2enmod headers 
$ apache2ctl -M | grep headers
headers_module (shared)

Conclusion

As shown in this whitepaper, CSP header is required that allows the browser to apply the content security policy. We check the configuration followed with analyze CSP header and HSTS response headers of your website or your own reverse proxy.

By following these whitepaper such as minimizing the amount of data revealed to attackers. Using secure encryption algorithms, and implementing CSP headers and cipher suites, you can significantly enhance the security of your server.