nginx installation, security configuration and forwarding agent

Posted by nscipione on Tue, 08 Mar 2022 21:24:20 +0100


Nginx installation

1. Create a new user and group ngxuser:ngxuser

groupadd ngxuser 

useradd -m -g ngxuser ngxuser #-m automatically creates the home directory, - g specifies the group

2. Install dependent packages (nginx installation is installed by root user)

The two covered by red do not need to be installed

#Force all installations

rpm -Uvh *.rpm --nodeps --force

#Separate installation mode

rpm -ivh libmpc-1.0.1-3.el7.x86_64.rpm

#If there are interdependencies, you can also install more than one at a time, for example:

rpm -ivh glibc-2.17-317.el7.x86_64.rpm glibc-common-2.17-317.el7.x86_64.rpm

View gcc version: gcc - v

3. Install pcre

tar -zxvf pcre-8.35.tar.gz

cd pcre-8.35


make && make install

View pcre version: rpm -qa pcre

4. Install zlib

tar -zxvf zlib-1.2.11.tar.gz

cd zlib-1.2.11


make && make install

5. Install openssl

tar -zxvf openssl-1.1.1j.tar.gz
cd openssl-1.1.1j.tar
./config shared zlib --prefix=/usr/local/openssl
make install

After success, you can check the version of openssl

Command: openssl # version # or openssl # version -a

6. Install nginx

Note the paths of pcre, zlib and ssl here. I put the installation packages of ngxin, pcre, zlib and ssl under / usr/local /

tar -zxvf nginx-1.18.0.tar.gz

cd nginx-1.18.0

./configure --user=ngxuser--group=ngxuser--prefix=/usr/local/nginx --conf-path=/usr/local/nginx/conf/nginx.conf --with-http_stub_status_module --with-pcre=/usr/local/pcre-8.35 --with-zlib=/usr/local/zlib-1.2.11 --with-http_ssl_module --with-openssl=/usr/local/openssl-1.1.1j

make && make install

It may take a long time to execute make & & make install. Just wait patiently. The following message indicates that the installation is complete

#Configuration summary. The following information appears to indicate that the installation is successful
Configuration summary 
  + using PCRE library: /usr/local/pcre-8.35
  + using OpenSSL library: /usr/local/openssl-1.1.1j
  + using zlib library: /usr/local/zlib-1.2.11

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/local/nginx/sbin/nginx"
  nginx modules path: "/usr/local/nginx/modules"
  nginx configuration prefix: "/usr/local/nginx-1.18.0/conf"
  nginx configuration file: "/usr/local/nginx-1.18.0/conf/nginx.conf"
  nginx pid file: "/usr/local/nginx/logs/"
  nginx error log file: "/usr/local/nginx/logs/error.log"
  nginx http access log file: "/usr/local/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

7. Test

At this step, nginx has been installed. You can start nginx and use your browser to access the test results;

start-up nginx
cd /usr/local/nginx/sbin
#Check the configuration. If there is no error, start it. If there is an error, continue to check the error
./nginx -t
#start nginx 
#Reload nginx. After modifying the configuration, there is no need to restart the application and the service is not interrupted
./nginx -s reload
#Stop nginx
./nginx -s quit
#Force stop nginx
./nginx -s stop

The ssl key can be configured by myself if necessary. In the test environment, I generated a test key and put it in the following path

cd  /usr/local/nginx/conf

mkdir ssl

Then put the SSL authorization file in the path of / usr/local/nginx/conf/ssl

8.ngxin.conf configuration, this step is very important. If the configuration is wrong, ngxin can't get up

#Use the ngxuser user of the ngxuser user group to run the worker process of nginx
user ngxuser ngxuser;

#The number of working processes the CPU is configured as several processes
worker_processes  1;

#pid        logs/;

events {
    #The maximum number of external links allowed is 1024, accounting for about 1024*328/1024/1024=0.32M of memory
    worker_connections  1024;

http {
    include       mime.types;
    default_type  application/octet-stream;
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    sendfile        on;
    #tcp_nopush     on;
    keepalive_timeout  65;

    gzip  on;

        #Proxy address and port
        upstream my_server {
                server backup;                
    # HTTP server
    server {
        listen 8080;
                #Prevent slow http denial of service attacks
                client_header_timeout 10s;
                client_header_buffer_size 1k;
                large_client_header_buffers 4 1k;
                client_body_timeout 10s;
                client_body_buffer_size 1M;
                client_body_temp_path /usr/local/nginx/client_body_temp/;
                client_max_body_size 3M;                           
                include       mime.types;
                server_tokens off;  #Hide version number
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header REMOTE-HOST $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;     
                proxy_set_header Host $host;
               # Response header missing vulnerability, security policy, simple XSS attack protection configuration
               add_header X-Frame-Options 'SAMEORIGIN'; #Only frame nesting of this website is allowed
                add_header Content-Security-Policy "default-src 'self';script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src * data:; style-src 'self' 'unsafe-inline';";  #Only files of the same origin are allowed to be loaded
                add_header X-XSS-Protection '1;mode=block'; #XSS filter on
                add_header X-Content-Type-Options nosniff; #Disable sniffing file types
                add_header Referrer-Policy 'strict-origin-when-cross-origin';
                add_header X-Download-Options noopen;
            # SQL injection 
            if ($request_method !~* GET|POST) { return 444; } 
                #Using 444 error code can further reduce the load pressure on the server.  
                #Prevent SQL injection
                if ($query_string ~* (\$|'|--|[+|(%20)]union[+|(%20)]|[+|(%20)]insert[+|(%20)]|[+|(%20)]drop[+|(%20)]|[+|(%20)]truncate[+|(%20)]|[+|(%20)]update[+|(%20)]|[+|(%20)]from[+|(%20)]|[+|(%20)]grant[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]where[+|(%20)]|[+|(%20)]select[+|(%20)]|[+|(%20)]and[+|(%20)]|[+|(%20)]or[+|(%20)]|[+|(%20)]count[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]chr[+|(%20)]|[+|(%20)]mid[+|(%20)]|[+|(%20)]like[+|(%20)]|[+|(%20)]iframe[+|(%20)]|[\<|%3c]script[\>|%3e]|javascript|alert|webscan|dbappsecurity|style|confirm\(|innerhtml|innertext)(.*)$) { return 555; }
                if ($uri ~* (/~).*) { return 501; } 
                if ($uri ~* (\\x.)) { return 501; } 
                #Prevent SQL injection
                if ($query_string ~* "[;'<>].*") { return 509; } 
                if ($request_uri ~ " ") { return 509; } 
                if ($request_uri ~ (\/\.+)) { return 509; } 
                if ($request_uri ~ (\.+\/)) { return 509; } 
                #if ($uri ~* (insert|select|delete|update|count|master|truncate|declare|exec|\*|\')(.*)$ ) { return 503; } #Prevent SQL injection
                if ($request_uri ~* "(cost\()|(concat\()") { return 504; } 
                if ($request_uri ~* "[+|(%20)]union[+|(%20)]") { return 504; } 
                if ($request_uri ~* "[+|(%20)]and[+|(%20)]") { return 504; } 
                if ($request_uri ~* "[+|(%20)]select[+|(%20)]") { return 504; } 
                if ($request_uri ~* "[+|(%20)]or[+|(%20)]") { return 504; } 
                if ($request_uri ~* "[+|(%20)]delete[+|(%20)]") { return 504; } 
                if ($request_uri ~* "[+|(%20)]update[+|(%20)]") { return 504; } 
                if ($request_uri ~* "[+|(%20)]insert[+|(%20)]") { return 504; } 
                if ($query_string ~ "(<|%3C).*script.*(>|%3E)") { return 505; } 
                if ($query_string ~ "GLOBALS(=|\[|\%[0-9A-Z]{0,2})") { return 505; } 
                if ($query_string ~ "_REQUEST(=|\[|\%[0-9A-Z]{0,2})") { return 505; } 
                if ($query_string ~ "proc/self/environ") { return 505; } 
                if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|\%3D)") { return 505; } 
                if ($query_string ~ "base64_(en|de)code\(.*\)") { return 505; } 
                if ($query_string ~ "[a-zA-Z0-9_]=http://") { return 506; } 
                if ($query_string ~ "[a-zA-Z0-9_]=(\.\.//?)+") { return 506; } 
                if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") { return 506; } 
                if ($query_string ~ "b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)b") { return 507; } 
                if ($query_string ~ "b(erections|hoodia|huronriveracres|impotence|levitra|libido)b") {return 507; } 
                if ($query_string ~ "b(ambien|bluespill|cialis|cocaine|ejaculation|erectile)b") { return 507; } 
                if ($query_string ~ "b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)b") { return 507; }
                 #Here, you can add or delete the above judgment parameters according to your own situation. Shielding such as cURL and wget is a little extreme, but "you'd rather kill a thousand by mistake than let one go".  
                if ($http_user_agent ~* YisouSpider|ApacheBench|WebBench|Jmeter|JoeDog|Havij|GetRight|TurnitinBot|GrabNet|masscan|mail2000|github|wget|curl|Java|python) { return 508; } 
                #As above, you can add or delete the following shielding and interception parameters according to the actual situation of your site.  
                if ($http_user_agent ~* "Go-Ahead-Got-It") { return 508; } 
                if ($http_user_agent ~* "GetWeb!") { return 508; } 
                if ($http_user_agent ~* "Go!Zilla") { return 508; } 
                if ($http_user_agent ~* "Download Demon") { return 508; } 
                if ($http_user_agent ~* "Indy Library") { return 508; } 
                if ($http_user_agent ~* "libwww-perl") { return 508; } 
                if ($http_user_agent ~* "Nmap Scripting Engine") { return 508; } 
                if ($http_user_agent ~* "") { return 508; } 
                if ($http_user_agent ~* "WebBench*") { return 508; } 
                #This will affect some domestic search engine crawlers, such as Sogou
                if ($http_user_agent ~* "spider") { return 508; } 
                #The log of each UA request can be used as a reference for analysis.
                if ($http_referer ~* { return 509; } 
                #Intercept 17ce Com site speed measurement node request, so Mingyue has always said that the data of these speed measurement websites are for reference only and can't be taken seriously.  
                if ($http_referer ~* WebBench*") { return 509; } 
                #Intercept WebBench or similar stress testing tools. Other tools only need to change their names.

                 #Anti theft chain, need to modify the website
                 #be careful! The configuration of the agent anti-theft chain is different from that of the local server anti-theft chain. My server is only used for agents and does not put static resources. If there are static resources, you can modify the root path
                location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
                        expires 30d; 
                        access_log off;
                        valid_referers none blocked *;
                        if ($invalid_referer) {
                            return 403;
                            #rewrite ^/;
                        proxy_pass http://my_server;
        location / { 
                proxy_pass http://my_server/;    
                proxy_redirect off;
                #proxy_redirect http://my_server/myApp/ http://$host:$server_port/;

 9. Set nginx boot

1. Edit nginx Service file. Starting from a certain version (forget which one), CentOS's startup and loading strategy has changed. Don't use it wrong. Mine is centos7 four

vi /usr/lib/systemd/system/nginx.service

Paste the following content into nginx Inside the service

PIDFile=/usr/local/nginx/logs/ #Don't be short here, otherwise there will be problems. I made a big detour here. Finally, I found the problem by reading the linux manual
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit

[Unit]: description of the service

Description: Service Description

After: describes the service category

[Service] setting of Service running parameters

Type=forking is the form of background operation

ExecStart is the specific running command of the service

ExecReload is the restart command

ExecStop is the stop command

PrivateTmp=True indicates that an independent temporary space is allocated to the service

Note: absolute paths are required for the start, restart and stop commands of [Service]

[Install] the relevant settings for service installation under the run level can be set to multi-user, that is, the system run level is 3

2. Set startup and self startup

systemctl start nginx.service   #Start service

systemctl enable nginx.service   #Power on self start

systemctl daemon-reload   #If the previous setting fails, execute this command to reload the daemon when setting again, and then execute enable;

After setting the boot, check whether the setting is successful

systemctl  list-unit-files | grep enabled


#Common commands

systemctl status nginx.service # view nginx status

systemctl start nginx.service # start nginx

systemctl stop nginx.service # stop nginx

systemctl reload nginx.service # restart nginx. This command is very common

10. Hide the Server field in the response header of nginx

1. stop it nginx Service, access nginx Source directory (not the installation directory, but the directory extracted before installation);
2. vi src/http/ngx_http_header_filter_module.c  #Lines 49-50 (HTTP ResponseHeader response header)
Original content:
static char ngx_http_server_string[] = "Server: nginx" CRLF;
static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;
Change to:
static char ngx_http_server_string[] = "Server:myServerName" CRLF;
static char ngx_http_server_full_string[] = "Server:myServerName " CRLF;

3. vi src/core/nginx.h (Nginx Internal name)
Modify, do not delete the previous#: 
#define NGINX_VERSION "1.0″    
#define NGINX_VER "myServerName/" NGINX_VERSION

4. vi src/http/ngx_http_special_response.c(Bottom of error page Footer)

After setting, you have to reinstall nginx,

./configure --user=ngxuser--group=ngxuser--prefix=/usr/local/nginx --conf-path=/usr/local/nginx/conf/nginx.conf --with-http_stub_status_module --with-pcre=/usr/local/pcre-8.35 --with-zlib=/usr/local/zlib-1.2.11 --with-http_ssl_module --with-openssl=/usr/local/openssl-1.1.1j

Install and compile
make && make install

11.Linux security settings

  1. Firewall settings

View firewall status
systemctl status firewalld
 Open firewall
systemctl start firewalld
 Turn off the firewall
systemctl stop firewalld
 Boot firewall
systemctl enable firewalld
systemctl is -enable firewalld #Check whether to start
 Turn off boot firewall
systemctl disable firewalld

Set the policy and port, and only open the required port and request protocol
sudo firewall-cmd --zone=public --permanent --add-service=https
firewall-cmd --zone=public --add-port=443/tcp --permanent
 Reload policy
sudo firewall-cmd --reload

Check whether all services opened by the firewall are enabled HTTP Service.
sudo firewall-cmd --list-service

2. linux prohibits the root user from logging in. I set this, but it's useless, because nginx must be started by the root user

Root user login is prohibited, and only ordinary users are allowed to use su to switch to root;

We have created the ngxuser user. The following steps need not be performed

1) create ordinary user: useradd ngxuser

2) set password: passwd ngxuser

3) prohibit the root user from logging in

    vi /etc/ssh/sshd_config

    PermitRootLogin no

Then execute

systemctl restart sshd

If you want to change it, just comment out permitrotlogin

vi /etc/ssh/sshd_config

#PermitRootLogin no

Then execute

systemctl restart sshd


3. Modify ssh default port 22

The following changes the port to 56588, which can be changed according to needs. It is best to choose the port within 10000-65535

Check whether the port is occupied

 netstat -lnp | grep 56588


1. Modify / etc/ssh/sshd_config

    vi /etc/ssh/sshd_config   

Port 22 //Port 22 is not deleted here to prevent the modified new port from being inaccessible, which makes it impossible to connect to the server with ssh.)

Port 56588


2. Set firewall through port

firewall-cmd --zone=public --add-port=56588/tcp --permanent

Reload policy

sudo firewall-cmd --reload

Query whether the port is enabled

firewall-cmd --permanent --query-port=56588/tcp

3. Modify SELinux

  1. Viewing seLinux status


2) Turn seLinux on and off

Setenforce1 #0: off, 1: Yes on

3) View seLinux open ports

semanage port -l | grep ssh

4) Add new port

semanage port -a -t ssh_port_t -p tcp 56588

5) Modify, save and restart sshd service

systemctl restart sshd   #systemctl restart sshd.service

6) Close port 22

vi /etc/ssh/sshd_config

#Port 22

Port 56588

Firewall delete open port

firewall-cmd --zone=public --remove-port=22/tcp --permanent

Reload policy

sudo firewall-cmd --reload


Topics: Linux CentOS Nginx server