Is there an efficient way to hide nginx from Nmap's Version Detection scan (nmap -sV)? The following is a sample result, we are trying to hide the nginx (reverse proxy) string.

80/tcp open  http    nginx (reverse proxy)

There's a way where Nginx manually filters nmap requests through the request's User Agent string, but it seems too costly due to nginx's if-else filtering. Are there other ways to hide nginx from nmap?

  • As far as I know it is not possible because nmap request is indistinguishable from a legitimate request. Even of you try to tell legitimate requests from nmap people will be eventually find the workaround can cause too many false positive problems. So most systems won't try to hide it Commented Jul 19, 2021 at 7:32
  • User Agent too can be inserted to make it look legitimate for instance by nmap command line. Commented Jul 19, 2021 at 7:33
  • If your port is open in an open network, expect it to be discovered because someone actually trying to attack your network would definitely not be stopped by user-agent filtering which is easy to bypass if you know nmap Commented Jul 19, 2021 at 7:38

1 Answer 1


If you want to protect your web server from attacks and scans like the one made by nmap, I would recommend you to follow this nginx hardening guide.

This guide contains the following security measures:

  • Disable Any Unwanted nginx Modules
  • Disable nginx server_tokens
  • Control Resources and Limits
  • Disable Any Unwanted HTTP methods
  • Install ModSecurity for Your nginx Web Server
  • Set Up and Configure nginx Access and Error Logs
  • Monitor nginx Access and Error Logs
  • Configure Nginx to Include Security Headers
  • Configure SSL and Cipher Suites
  • Update Your Server Regularly
  • Check Your Configuration with Gixy
  • You Don’t Have to Do It Manually (Automate)

With ModSecurity and Fail2Ban you can block Malicious User-Agents, pretty similar to what you mentioned above, here is a quick guide on how to do it. This may be a better option than manually doing the process.

Additionally, what you really want to do from what I read on your question is to hide the Banner displayed by nginx, this prevents Banner Grabbing attacks and identification of technologies used in your server.

You can reduce the amount of information showed by nginx by adding the following line to your nginx.conf file:

server_tokens off;

Then, restart your service. With this change you will configure nginx to not send any version numbers in the HTTP header.

nginx banner

You can also remove the server name or replace it with any string you want. However, since nginx modules cannot be dynamically loaded (according to Acunetix), you need to recompile nginx from source with the HttpHeadersMoreModule nginx module.

Here is a link in the Nginx forums where this topic was already discussed and it indicates the exact changes that you have to do in the nginx source code to hide the banner.

If you want to remove the name of the server completely you need to alter the source code prior to compiling.

Edit /path/to/nginx-0.*/src/http/ngx_http_header_filter_module.c lines 48 and 49:

static char ngx_http_server_string[] = "Server: nginx" CRLF;
static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;

Replace with any string you like, you can even put something like Apache in order to deceit attackers.

If you want to edit NGINX_VER, it is defined, along with some other relevant constants, in /path/to/nginx-0.*/src/core/nginx.h, lines 11-13.

Finally, as a workaround that I found, you can do the following to change the banner without requiring to compile nginx from source code:

  1. Install nginx-extras:

    sudo apt install -y nginx-extras
  2. Edit your nginx.conf file, usually located in /etc/nginx/nginx.conf and add the following 2 lines:

    more_clear_headers Server;
    more_set_headers 'Server: Nothing';

    Please note that you can put any string you like, in my case this is my configuration file to simulate a Google Web Server banner:

    galoget@hackem:~$ cat /etc/nginx/nginx.conf
    user www-data;
    worker_processes auto;
    pid /run/nginx.pid;
    include /etc/nginx/modules-enabled/*.conf;
    events {
       worker_connections 768;
       # multi_accept on;
    http {
       # Basic Settings
       sendfile on;
       tcp_nopush on;
       tcp_nodelay on;
       keepalive_timeout 65;
       types_hash_max_size 2048;
       server_tokens off;
       include /etc/nginx/mime.types;
       default_type application/octet-stream;
       # SSL Settings
       ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref:    POODLE
       ssl_prefer_server_ciphers on;
       # Logging Settings
       access_log /var/log/nginx/access.log;
       error_log /var/log/nginx/error.log;
       # Gzip Settings
       gzip on;
       # Virtual Host Configs
       include /etc/nginx/conf.d/*.conf;
       include /etc/nginx/sites-enabled/*;
       # Custom Banner Message - Set to show GWS (Google Web Server)
       more_clear_headers Server;
       more_set_headers 'Server: gws';
  3. Check the syntax of your configuration file to see if everything is OK:

    sudo nginx -t
  4. Reload or restart your nginx service:

    sudo systemctl reload nginx

I just tested these steps and are working perfectly, please see the screenshots below:

Before doing the previous steps:

In this image I include the server headers with server_tokens off; added to the config file, so no specific version of nginx is shown:

default nginx banner

After doing the previous steps:

custom nginx banner

Additional References:

Hope you find this complete guide useful.


Not the answer you're looking for? Browse other questions tagged .