One place for hosting & domains


      How To Harden OpenSSH on Ubuntu 18.04

      The author selected the Electronic Frontier Foundation Inc to receive a donation as part of the Write for DOnations program.


      Linux servers are often administered remotely using SSH by connecting to an OpenSSH server, which is the default SSH server software used within Ubuntu, Debian, CentOS, FreeBSD, and most other Linux/BSD-based systems.

      OpenSSH server is the server side of SSH, also known as SSH daemon or sshd. You can connect to an OpenSSH server using the OpenSSH client—the ssh command. You can learn more about the SSH client-server model in SSH Essentials: Working with SSH Servers, Clients, and Keys. Properly securing your OpenSSH server is very important, as it acts as the front door or entry into your server.

      In this tutorial, you will harden your OpenSSH server by using different configuration options to ensure that remote access to your server is as secure as possible.


      To complete this tutorial, you will need:

      Once you have this ready, log in to your server as your non-root user to begin.

      Step 1 — General Hardening

      In this first step, you will implement some initial hardening configurations to improve the overall security of your SSH server.

      The exact hardening configuration that is most suitable for your own server depends heavily on your own threat model and risk threshold. However, the configuration you’ll use in this step is a general secure configuration that will suit the majority of servers.

      Many of the hardening configurations for OpenSSH you implement using the standard OpenSSH server configuration file, which is located at /etc/ssh/sshd_config. Before continuing with this tutorial, it is recommended to take a backup of your existing configuration file, so that you can restore it in the unlikely event that something goes wrong.

      Take a backup of the file using the following command:

      • sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

      This will save a backup copy of the file to /etc/ssh/sshd_config.bak.

      Before editing your configuration file, you can review the options that are currently set. To do this, run the following command:

      This will run OpenSSH server in extended test mode, which will validate the full configuration file and print out the effective configuration values.

      You can now open the configuration file using your favorite text editor to begin implementing the initial hardening measures:

      • sudo nano /etc/ssh/sshd_config

      Note: The OpenSSH server configuration file includes many default options and configurations. Depending on your existing server configuration, some of the recommended hardening options may already have been set.

      When editing your configuration file, some options may be commented out by default using a single hash character (#) at the start of the line. In order to edit these options, or have the commented option be recognized, you’ll need to uncomment them by removing the hash.

      Firstly, disable logging in via SSH as the root user by setting the following option:


      PermitRootLogin no

      This is massively beneficial, as it will prevent a potential attacker from logging in directly as root. It also encourages good operational security practices, such as operating as a non-privileged user and using sudo to escalate privileges only when absolutely needed.

      Next, you can limit the maximum number of authentication attempts for a particular login session by configuring the following:


      MaxAuthTries 3

      A standard value of 3 is acceptable for most setups, but you may wish to set this higher or lower depending on your own risk threshold.

      If required, you can also set a reduced login grace period, which is the amount of time a user has to complete authentication after initially connecting to your SSH server:


      LoginGraceTime 20

      The configuration file specifies this value in seconds.

      Setting this to a lower value helps to prevent certain denial-of-service attacks where multiple authentication sessions are kept open for a prolonged period of time.

      If you have configured SSH keys for authentication, rather than using passwords, disable SSH password authentication to prevent leaked user passwords from allowing an attacker to log in:


      PasswordAuthentication no

      As a further hardening measure related to passwords, you may also wish to disable authentication with empty passwords. This will prevent logins if a user’s password is set to a blank or empty value:


      PermitEmptyPasswords no

      In the majority of use cases, SSH will be configured with public key authentication as the only in-use authentication method. However, OpenSSH server also supports many other authentication methods, some of which are enabled by default. If these are not required, you can disable them to further reduce the attack surface of your SSH server:


      ChallengeResponseAuthentication no
      KerberosAuthentication no
      GSSAPIAuthentication no

      If you’d like to know more about some of the additional authentication methods available within SSH, you may wish to review these resources:

      X11 forwarding allows for the display of remote graphical applications over an SSH connection, but this is rarely used in practice. It is recommended to disable it if it isn’t needed on your server:


      X11Forwarding no

      OpenSSH server allows connecting clients to pass custom environment variables, that is, to set a $PATH or to configure terminal settings. However, like X11 forwarding, these are not commonly used, so can be disabled in most cases:


      PermitUserEnvironment no

      If you decide to configure this option, you should also make sure to comment out any references to AcceptEnv by adding a hash (#) to the beginning of the line.

      Next, you can disable several miscellaneous options related to tunneling and forwarding if you won’t be using these on your server:


      AllowAgentForwarding no
      AllowTcpForwarding no
      PermitTunnel no

      Finally, you can disable the verbose SSH banner that is enabled by default, as it shows various information about your system, such as the operating system version:


      DebianBanner no

      Note that this option most likely won’t already be present in the configuration file, so you may need to add it manually. Save and exit the file once you’re done.

      Now validate the syntax of your new configuration by running sshd in test mode:

      If your configuration file has a valid syntax, there will be no output. In the event of a syntax error, there will be an output describing the issue.

      Once you’re satisfied with your configuration file, you can reload sshd to apply the new settings:

      In this step, you completed some general hardening of your OpenSSH server configuration file. Next, you’ll implement an IP address allowlist to further restrict who can log in to your server.

      Step 2 — Implementing an IP Address Allowlist

      You can use IP address allowlists to limit the users who are authorized to log in to your server on a per-IP address basis. In this step, you will configure an IP allowlist for your OpenSSH server.

      In many cases, you will only be logging on to your server from a small number of known, trusted IP addresses. For example, your home internet connection, a corporate VPN appliance, or a static jump box or bastion host in a data center.

      By implementing an IP address allowlist, you can ensure that people will only be able to log in from one of the pre-approved IP addresses, greatly reducing the risk of a breach in the event that your private keys and/or passwords are leaked.

      Note: Please take care in identifying the correct IP addresses to add to your allowlist, and ensure that these are not floating or dynamic addresses that may regularly change, for example as is often seen with consumer internet service providers.

      You can identify the IP address that you’re currently connecting to your server with by using the w command:

      This will output something similar to the following:


      14:11:48 up 2 days, 12:25, 1 user, load average: 0.00, 0.00, 0.00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT your_username pts/0 12:24 1.00s 0.20s 0.00s w

      Locate your user account in the list and take a note of the connecting IP address. Here we use the example IP of

      In order to begin implementing your IP address allowlist, open the OpenSSH server configuration file in your favorite text editor:

      • sudo nano /etc/ssh/sshd_config

      You can implement IP address allowlists using the AllowUsers configuration directive, which restricts user authentications based on username and/or IP address.

      Your own system setup and requirements will determine which specific configuration is the most appropriate. The following examples will help you to identify the most suitable one:

      • Restrict all users to a specific IP address:
      AllowUsers *@
      AllowUsers *@
      • Restrict all users to a specific IP address range (using wildcards):
      AllowUsers *@203.0.113.*
      • Restrict all users to multiple specific IP addresses and ranges:
      AllowUsers *@ *@ *@ *@172.16.*.1
      • Disallow all users except for named users from specific IP addresses:
      AllowUsers sammy@ alex@<^>
      • Restrict a specific user to a specific IP address, while continuing to allow all other users to log in without restrictions:
      Match User ashley
        AllowUsers ashley@

      Warning: Within an OpenSSH configuration file, all configurations under a Match block will only apply to connections that match the criteria, regardless of indentation or line breaks. This means that you must be careful and ensure that configurations intended to apply globally are not accidentally put within a Match block. It is recommended to put all Match blocks at the bottom/end of your configuration file to help avoid this.

      Once you have finalized your configuration, add it to the bottom of your OpenSSH server configuration file:


      AllowUsers *@

      Save and close the file, and then proceed to test your configuration syntax:

      If no errors are reported, you can reload OpenSSH server to apply your configuration:

      In this step, you implemented an IP address allowlist on your OpenSSH server. Next, you will restrict the shell of a user to limit the commands that they are allowed to use.

      Step 3 — Restricting the Shell of a User

      In this step, you’ll look at the various options for restricting the shell of an SSH user.

      In addition to providing remote shell access, SSH is also great for transferring files and other data, for example, via SFTP. However, you may not always want to grant full shell access to users when they only need to be able to carry out file transfers.

      There are multiple configurations within OpenSSH server that you can use to restrict the shell environment of particular users. For instance, in this tutorial, we will use these to create SFTP-only users.

      Firstly, you can use the /usr/sbin/nologin shell to disable interactive logins for certain user accounts, while still allowing non-interactive sessions to function, like file transfers, tunneling, and so on.

      To create a new user with the nologin shell, use the following command:

      • sudo adduser --shell /usr/sbin/nologin alex

      Alternatively, you can change the shell of an existing user to be nologin:

      • sudo usermod --shell /usr/sbin/nologin sammy

      If you then attempt to interactively log in as one of these users, the request will be rejected:

      This will output something similar to the following message:


      This account is currently not available.

      Despite the rejection message on interactive logins, other actions such as file transfers will still be allowed.

      Next, you should combine your usage of the nologin shell with some additional configuration options to further restrict the relevant user accounts.

      Begin by opening the OpenSSH server configuration file in your favorite text editor again:

      • sudo nano /etc/ssh/sshd_config

      There are two configuration options that you can implement together to create a tightly restricted SFTP-only user account: ForceCommand internal-sftp and ChrootDirectory.

      The ForceCommand option within OpenSSH server forces a user to execute a specific command upon login. This can be useful for certain machine-to-machine communications, or to forcefully launch a particular program.

      However, in this case, the internal-sftp command is particularly useful. This is a special function of OpenSSH server that launches a basic in-place SFTP daemon that doesn’t require any supporting system files or configuration.

      This should ideally be combined with the ChrootDirectory option, which will override/change the perceived root directory for a particular user, essentially restricting them to a specific directory on the system.

      Add the following configuration section to your OpenSSH server configuration file for this:


      Match User alex
        ForceCommand internal-sftp
        ChrootDirectory /home/alex/

      Warning: As noted in Step 2, within an OpenSSH configuration file, all configurations under a Match block will only apply to connections that match the criteria, regardless of indentation or line breaks. This means that you must be careful and ensure that configurations intended to apply globally are not accidentally put within a Match block. It is recommended to put all Match blocks at the bottom/end of your configuration file to help avoid this.

      Save and close your configuration file, and then test your configuration again:

      If there are no errors, you can then apply your configuration:

      This has created a robust configuration for the alex user, where interactive logins are disabled, and all SFTP activity is restricted to the home directory of the user. From the perspective of the user, the root of the system, that is, /, is their home directory, and they will not be able to traverse up the file system to access other areas.

      You’ve implemented the nologin shell for a user and then created a configuration to restrict SFTP access to a specific directory.

      Step 4 — Advanced Hardening

      In this final step, you will implement various additional hardening measures to make access to your SSH server as secure as possible.

      A lesser-known feature of OpenSSH server is the ability to impose restrictions on a per-key basis, that is restrictions that apply only to specific public keys present in the .ssh/authorized_keys file. This is particularly useful to control access for machine-to-machine sessions, as well as providing the ability for non-sudo users to control the restrictions for their own user account.

      You can apply most of these restrictions at the system or user level too, however it is still advantageous to implement them at the key-level as well, to provide defence-in-depth and an additional failsafe in the event of accidental system-wide configuration errors.

      Note: You can only implement these additional security configurations if you’re using SSH public-key authentication. If you’re only using password authentication, or have a more complex setup such as an SSH certificate authority, unfortunately these will not be usable.

      Begin by opening your .ssh/authorized_keys file in your favorite text editor:

      • nano ~/.ssh/authorized_keys

      Note: Since these configurations apply on a per-key basis, you’ll need to edit each individual key within each individual authorized_keys file that you want them to apply to, for all users on your system. Usually you will only need to edit one key/file, but this is worth considering if you have a complex multi-user system.

      Once you’ve opened your authorized_keys file, you will see that each line contains an SSH public key, which will most likely begin with something like ssh-rsa AAAB.... Additional configuration options can be added to the beginning of the line, and these will only apply to successful authentications against that specific public key.

      The following restriction options are available:

      • no-agent-forwarding: Disable SSH agent forwarding.
      • no-port-forwarding: Disable SSH port forwarding.
      • no-pty: Disable the ability to allocate a tty (i.e. start a shell).
      • no-user-rc: Prevent execution of the ~/.ssh/rc file.
      • no-X11-forwarding: Disable X11 display forwarding.

      You can apply these to disable specific SSH features for specific keys. For example, to disable agent forwarding and X11 forwarding for a key, you would use the following configuration:


      no-agent-forwarding,no-X11-forwarding ssh-rsa AAAB...

      By default, these configurations work using an “allow by default, block by exception” methodology; however, it is also possible to use “block by default, allow by exception,” which is generally preferable for ensuring security.

      You can do this by using the restrict option, which will implicitly deny all SSH features for the specific key, requiring them to be explicitly re-enabled only where absolutely needed. You can re-enable features using the same configuration options described earlier in this tutorial, but without the no- prefix.

      For example, to disable all SSH features for a particular key, apart from X11 display forwarding, you can use the following configuration:


      restrict,X11-forwarding ssh-rsa AAAB...

      You may also wish to consider using the command option, which is very similar to the ForceCommand option described in Step 3. This doesn’t provide a direct benefit if you’re already using ForceCommand, but it is good defense-in-depth to have it in place, just in the unlikely event that your main OpenSSH server configuration file is overwritten, edited, and so on.

      For example, to force users authenticating against a specific key to execute a specific command upon login, you can add the following configuration:


      command="top" ssh-rsa AAAB...

      Warning: The command configuration option acts purely as a defense-in-depth method, and should not be solely relied on to restrict the activities of an SSH user, as there are potentially ways to override or bypass it depending on your environment. Instead, you should use the configuration in tandem with the other controls described in this article.

      Finally, to best use the per-key restrictions for the SFTP-only user that you created in Step 3, you can use the following configuration:


      restrict,command="false" ssh-rsa AAAB...

      The restrict option will disable all interactive access, and the command="false" option acts as a second line of defense in the event that the ForceCommand option or nologin shell were to fail.

      Save and close the file to apply the configuration. This will take effect immediately for all new logins, so you don’t need to reload OpenSSH manually.

      In this final step, you implemented some additional advanced hardening measures for OpenSSH server by using the custom options within your .ssh/authorized_keys file(s).


      In this article, you reviewed your OpenSSH server configuration and implemented various hardening measures to help secure your server.

      This will have reduced the overall attack surface of your server by disabling unused features and locking down the access of specific users.

      You may wish to review the manual pages for OpenSSH server and its associated configuration file, to identify any potential further tweaks that you want to make.

      Source link

      Recommended Steps To Harden Apache HTTP on FreeBSD 12.0

      The author selected the Free and Open Source Fund to receive a donation as part of the Write for DOnations program.


      Although the default installation of an Apache HTTP server is already safe to use, its configuration can be substantially improved with a few modifications. You can complement already present security mechanisms, for example, by setting protections around cookies and headers, so connections can’t be tampered with at the user’s client level. By doing this you can dramatically reduce the possibilities of several attack methods, like Cross-Site Scripting attacks (also known as XSS). You can also prevent other types of attacks, such as Cross-Site Request Forgery, or session hijacking, as well as Denial of Service attacks.

      In this tutorial you’ll implement some recommended steps to reduce how much information on your server is exposed. You will verify the directory listings and disable indexing to check the access to resources. You’ll also change the default value of the timeout directive to help mitigate Denial of Service type of attacks. Furthermore you’ll disable the TRACE method so sessions can’t be reversed and hijacked. Finally you’ll secure headers and cookies.

      Most of the configuration settings will be applied to the Apache HTTP main configuration file found at /usr/local/etc/apache24/httpd.conf.


      Before you begin this guide you’ll need the following:

      With the prerequisites in place you have a FreeBSD system with a stack on top able to serve web content using anything written in PHP, such as major CMS software. Furthermore, you’ve encrypted safe connections through Let’s Encrypt.

      Reducing Server Information

      The operating system banner is a method used by computers, servers, and devices of all kinds to present themselves into networks. Malicious actors can use this information to gain exploits into the relevant systems. In this section you’ll reduce the amount of information published by this banner.

      Sets of directives control how this information is displayed. For this purpose the ServerTokens directive is important; by default it displays all details about the operating system and compiled modules to the client that’s connecting to it.

      You’ll use a tool for network scanning to check what information is currently revealed prior to applying any changes. To install nmap run the following command:

      To get your server’s IP address, you can run the following command:

      • ifconfig vtnet0 | awk '/inet / {print $2}'

      You can check the web server response by using the following command:

      • nmap -sV -p 80 your-server-ip

      You invoke nmap to make a scan (hence the -s flag), to display the version (the -V flag) on port 80 (the -p flag) on the given IP or domain.

      You’ll receive information about your web server, similar to the following:


      Starting Nmap 7.80 ( ) at 2020-01-22 00:30 CET Nmap scan report for Host is up (0.054s latency). PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.41 ((FreeBSD) OpenSSL/1.1.1d-freebsd Service detection performed. Please report any incorrect results at . Nmap done: 1 IP address (1 host up) scanned in 7.59 seconds

      This output shows that information such as the operating system, the Apache HTTP version, and OpenSSL are visible. This can be useful for attackers to gain information about the server and choose the right tools to exploit, for example, a vulnerability in the software running on the server.

      You’ll place the ServerTokens directive in the main configuration file since it doesn’t come configured by default. The lack of this configuration makes Apache HTTP display the full information about the server as the documentation states. To limit the information that is revealed about your server and configuration, you’ll place the ServerTokens directive inside the main configuration file.

      You’ll place this directive following the ServerName entry in the configuration file. Run the following command to find the directive

      • grep -n 'ServerName' /usr/local/etc/apache24/httpd.conf

      You’ll find the line number that you can then search with vi:


      226 #ServerName

      Run the following command:

      • sudo vi +226 /usr/local/etc/apache24/httpd.conf

      Add the following highlighted line:


      . . .
      ServerTokens Prod

      Save and exit the file with :wq and ENTER.

      Setting the ServerTokens directive to Prod will make it only display that this is an Apache web server.

      For this to take effect restart the Apache HTTP server:

      To test the changes, run the following command:

      • nmap -sV -p 80 your-server-ip

      You’ll see similar output to the following with more minimal information on your Apache web server:


      Starting Nmap 7.80 ( ) at 2020-01-22 00:58 CET Nmap scan report for WPressBSD ( Host is up (0.056s latency). PORT STATE SERVICE VERSION 80/tcp open http Apache httpd Service detection performed. Please report any incorrect results at . Nmap done: 1 IP address (1 host up) scanned in 7.59 seconds

      You’ve seen what information the server was announcing prior to the change and you’ve now reduced this to the minimum. With this you’re providing fewer clues about your server to an external actor. In the next step you’ll manage the directory listings for your web server.

      Managing Directory Listings

      In this step you’ll ensure the directory listing is correctly configured, so the right parts of the system are publicly available as intended, while the remainder are protected.

      Note: When an argument is declared it is active, but the + can visually reinforce it is in fact enabled. When a minus sign - is placed the argument is denied, for example, Options -Indexes.

      Arguments with + and/or - can not be mixed, it is considered bad syntax in Apache HTTP and it may be rejected at the start up.

      Adding the statement Options -Indexes will set the content inside the data path /usr/local/www/apache24/data to not index (read listed) automatically if an .html file doesn’t exist, and not show if a URL maps this directory. This will also apply when using virtual host configurations such as the one used for the prerequisite tutorial for the Let’s Encrypt certificate.

      You will set the Options directive with the -Indexes argument and with the +FollowSymLinks directive, which will allow symbolic links to be followed. You’ll use the + symbol in order to comply with Apache’s HTTP conventions.

      Run the following command to find the line to edit in the configuration file:

      • grep -n 'Options Indexes FollowSymLinks' /usr/local/etc/apache24/httpd.conf

      You’ll see output similar to the following:


      263 : Options Indexes FollowSymLinks

      Run this command to directly access the line for editing:

      • sudo vi +263 /usr/local/etc/apache24/httpd.conf

      Now edit the line as per the configuration:


      . . .
      Options -Indexes +FollowSymLinks
      . . .

      Save and exit the file with :wq and ENTER.

      Restart Apache HTTP to implement these changes:

      At your domain in the browser, you’ll see a forbidden access message, also known as the 403 error. This is due to the changes you’ve applied. Placing -Indexes into the Options directive has disabled the auto-index capability of Apache HTTP and therefore there’s no index.html file inside the data path.

      You can solve this by placing an index.html file inside the VirtualHost you enabled in the prerequisite tutorial for the Let’s Encrypt certificate. You’ll use the default block within Apache HTTP and place it in the same folder as the DocumentRootthat you declared in the virtual host.


      <VirtualHost *:80>
          DocumentRoot "/usr/local/www/apache24/data/"
          ErrorLog "/var/log/"
          CustomLog "/var/log/" common

      Use the following command to do this:

      • sudo cp /usr/local/www/apache24/data/index.html /usr/local/www/apache24/data/

      Now you’ll see an It works! message when visiting your domain.

      In this section you’ve placed restrictions to the Indexes directive to not automatically enlist and display content other than what you intend. Now if there is not an index.html file inside the data path Apache HTTP will not automatically create an index of contents. In the next step you’ll move beyond obscuring information and customize different directives.

      Reducing the Timeout Directive Value

      The Timeout directive sets the limit of time Apache HTTP will wait for new input/output before failing the connection request. This failure can occur due to different circumstances such as packets not arriving to the server or data not being confirmed as received by the client.

      By default the timeout is set to 60 seconds. In environments where the internet service is slow this default value may be sensible, but one minute is quite a long time particularly if the server is covering a target of users with faster internet service. Furthermore the time during which the server is not closing the connection can be abused to perform Denial of Service attacks (DoS). If a flood of these malicious connections occurs the server will stumble and possibly become saturated and irresponsive.

      To change the value you’ll find the Timeout entries in the httpd-default.conf file:

      • grep -n 'Timeout' /usr/local/etc/apache24/extra/httpd-default.conf

      You’ll see similar output to:


      8 # Timeout: The number of seconds before receives and sends time out. 10 Timeout 60 26 # KeepAliveTimeout: Number of seconds to wait for the next request from the 29 KeepAliveTimeout 5 89 RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500

      In the output line 10 sets the Timeout directive value. To directly access this line run the following command:

      • sudo vi +10 /usr/local/etc/apache24/extra/httpd-default.conf

      You’ll change it to 30 seconds, for example, like the following:


      # Timeout: The number of seconds before receives and sends time out.
      Timeout 30

      Save and exit the file with :wq and ENTER.

      The value of the Timeout directive has to balance a time range large enough for those events to allow a legitimate and successful connection to happen, but short enough to prevent undesired connection attempts.

      Note: Denial of Service attacks can drain the server’s resources quite effectively. A complementary and very capable counter measure is using a threaded MPM to get the best performance out of how Apache HTTP handles connections and processes. In this tutorial How To Configure Apache HTTP with MPM Event and PHP-FPM on FreeBSD 12.0 there are steps on enabling this capability.

      For this change to take effect restart the Apache HTTP server:

      You’ve changed the default value of the Timeout directive in order to partially mitigate DoS attacks.

      Disabling the TRACE method

      The Hypertext Transport Protocol was developed following a client-server model and as such, the protocol has request methods to retrieve or place information from/to the server. The server needs to understand these sets of methods and the interaction between them. In this step you’ll configure the minimum necessary methods.

      TheTRACE method, which was considered harmless, was leveraged to perform Cross Site Tracing attacks. These types of attacks allow malicious actors to steal user sessions through that method. The method was designed for debugging purposes by the server returning the same request originally sent by the client. Because the cookie from the browser’s session is sent to the server it will be sent back again. However, this could potentially be intercepted by a malicious actor, who can then redirect a browser’s connection to a site of their control and not to the original server.

      Because of the possibility of the misuse of the TRACE method it is recommended to only use it for debugging and not in production. In this section you’ll disable this method.

      Edit the httpd.conf file with the following command and then press G to reach the end of the file:

      • sudo vi /usr/local/etc/apache24/httpd.conf

      Add the following entry path at the end of the file:


      . . .
      TraceEnable off

      A good practice is to only specify the methods you’ll use in your Apache HTTP web server. This will help limit potential entry points for malicious actors.

      LimitExcept can be useful for this purpose since it will not allow any other methods than those declared in it. For example a configuration can be established like this one:


      DocumentRoot "/usr/local/www/apache24/data"
      <Directory "/usr/local/www/apache24/data">
          Options -Indexes +FollowSymLinks -Includes
          AllowOverride none
           <LimitExcept GET POST HEAD>
             deny from all
          Require all granted

      As declared within the LimitExcept directive only the GET, POST, and HEAD methods are allowed in the configuration.

      • The GET method is part of the HTTP protocol and it is used to retrieve data.
      • The POST method is also part of the HTTP protocol and is used to send data to the server.
      • The HEAD method is similar to GET, however this has no response body.

      You’ll use the following command and place the LimitExcept block inside the file:

      • sudo vi +272 /usr/local/etc/apache24/httpd.conf

      To set this configuration you’ll place the following block into the DocumentRoot directive entry where the content will be read from, more specifically inside the Directory entry:


      . . .
      <LimitExcept GET POST HEAD>
         deny from all
      . . .

      To apply the changes restart Apache HTTP:

      The newer directive AllowedMethods provides similar functionality, although its status is still experimental.

      You’ve seen what HTTP methods are, their use, and the protection they offer from malicious activity leveraging the TRACE method as well as how to declare what methods to use. Next you’ll work with further protections dedicated to HTTP headers and cookies.

      Securing Headers and Cookies

      In this step you’ll set specific directives to protect the sessions that the client machines will open when visiting your Apache HTTP web server. This way your server will not load unwanted content, encryption will not be downgraded, and you’ll avoid content sniffing.

      Headers are components of the requests methods. There are headers to adjust authentication, communication between server and client, caching, content negotiation, and so on.

      Cookies are bits of information sent by the server to the browser. These bits allow the server to recognize the client browser from one computer to another. They also allow servers to recognize user sessions. For example, they can track a shopping cart of a logged-in user, payment information, history, and so on. Cookies are used and retained in the client’s web browser since HTTP is a stateless protocol, meaning once the connection closes the server does not remember the request sent by one client, or another one.

      It is important to protect headers as well as cookies because they provide communication between the web browser client and the web server.

      The headers module comes activated by default. To check if it’s loaded you’ll use the following command:

      • sudo apachectl -M | grep 'headers'

      You’ll see the following output:


      headers_module (shared)

      If you don’t see any output, check if the module is activated inside Apache’s httpd.conf file:

      • grep -n 'mod_headers' /usr/local/etc/apache24/httpd.conf

      As output you’ll see an uncommented line referring to the specific module for headers:


      . . .
      122  LoadModule headers_module libexec/apache24/
      . . .

      Remove the hashtag at the beginning of the line, if present, to activate the directive.

      By making use of the following Apache HTTP directives you’ll protect headers and cookies from malicious activity to reduce the risk for clients and servers.

      Now you’ll set the header’s protection. You’ll place all these header values in one block. You can choose to apply these values as you wish, but all are recommended.

      Edit the httpd.conf file with the following command and then press G to reach the end of the file:

      • sudo vi /usr/local/etc/apache24/httpd.conf

      Place the following block at the end of the file:


      . . .
      <IfModule mod_headers.c>
        # Add security and privacy related headers
        Header set Content-Security-Policy "default-src 'self'; upgrade-insecure-requests;"
        Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"
        Header always edit Set-Cookie (.*) "$1; HttpOnly; Secure"
        Header set X-Content-Type-Options "nosniff"
        Header set X-XSS-Protection "1; mode=block"
        Header set Referrer-Policy "strict-origin"
        Header set X-Frame-Options: "deny"
        SetEnv modHeadersAvailable true
      • Header set Strict-Transport-Security "max-age=31536000; includeSubDomains": HTTP Strict Transport Security (HTSTS) is a mechanism for web servers and clients (mainly browsers) to establish communications using only HTTPS. By implementing this you’re avoiding man-in-the-middle attacks, where a third party in between the communication could potentially access the bits, but also tamper with them.

      • Header always edit Set-Cookie (.*) "$1; HttpOnly; Secure": The HttpOnly and Secure flags on headers help prevent cross-site scripting attacks, also known as XSS. Cookies can be misused by attackers to pose as legitimate visitors presenting themselves as someone else (identity theft), or be tampered.

      • Header set Referrer-Policy "strict-origin": The Referrer-Policy header sets what information is included as the referrer information in the header field.

      • Header set Content-Security-Policy "default-src 'self'; upgrade-insecure-requests;": The Content-Security-Policy header (CSP) will completely prevent loading content not specified in the parameters, which is helpful to prevent cross-site scripting (XSS) attacks. There are many possible parameters to configure the policy for this header. The bottom line is configuring it to load content from the same site and upgrade any content with an HTTP origin.

      • Header set X-XSS-Protection "1; mode=block": This supports older browsers that do not cope with Content-Security-Policy headers. The ‘X-XSS-Protection’ header provides protection against Cross-Site Scripting attacks. You do not need to set this header unless you need to support old browser versions, which is rare.

      • Header set X-Frame-Options: "deny": This prevents clickjacking attacks. The 'X-Frame-Options’ header tells a browser if a page can be rendered in a <frame>, <iframe>, <embed>, or <object>. This way content from other sites cannot be embedded into others, preventing clickjacking attacks. Here you’re denying all frame render so the web page can’t be embedded anywhere else, not even inside the same web site. You can adapt this to your needs, if, for example, you must authorize rendering some pages because they are advertisements or collaborations with specific websites.

      • Header set X-Content-Type-Options "nosniff": The 'X-Content-Type-Options’ header controls MIME types so they’re not changed and followed. MIME types are file format standards; they work for text, audio, video, image, and so on. This header blocks malicious actors from content sniffing those files and trying to alter the file types.

      Now restart Apache for the changes to take effect:

      To check the security levels of your configuration settings, visit the security headers website. Having followed the steps in this tutorial, your domain will score an A grade.

      Note: If you make your headers check by visiting and get an F grade it could be because there is no index.html inside the DocumentRoot of your site as instructed at the end of Step 2. If checking your headers you get a different grade than an A or an F, check each Header set line looking for any misspelling that may have caused the downgrade.

      In this step you have worked with up to seven settings to improve the security of your headers and cookies. These will help prevent cross-site scripting, clickjacking, and other types of attacks.


      In this tutorial you’ve addressed several security aspects, from information disclosure, to protecting sessions, through setting alternative configuration settings for important functionality.

      For further resources on hardening Apache, here are some other references:

      For extra tools to protect Apache HTTP:

      Source link