In this tutorial, we will show you how to install and secure Nginx on an Ubuntu 22.04, 20.04, 18.04 server using Let’s Encrypt and iptables.
Prerequisites
- A server running Ubuntu 22.04, 20.04, 18.04.
- A non-root user with sudo privileges.
- Ensure that your system is up to date.
sudo apt update && sudo apt upgrade -yInstall Required Packages
First, you will need to install the required packages to your system. You can install all of them with the following command:
sudo apt install nginx iptables-persistent certbot python3-certbot-nginx curl -yOnce all the packages are installed, you can proceed to the next step.
Configure Firewall
Next, you will need to configure the firewall to allow HTTP and HTTPS traffic. You can do it with the following command:
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPTsudo iptables -A INPUT -p tcp --dport 443 -j ACCEPTNext, rate-limit the number of connections per IP address to prevent DDoS attacks:
sudo iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 20 --connlimit-mask 24 -j DROPsudo iptables -A INPUT -p tcp --syn --dport 443 -m connlimit --connlimit-above 20 --connlimit-mask 24 -j DROPNext, allow SSH traffic:
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPTNext, block invalid packets and new incoming packets that are not SYN:
iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROPiptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROPNext, allow established and related incoming traffic:
sudo iptables -A INPUT -p tcp --dport 80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPTsudo iptables -A OUTPUT -p tcp --sport 80,443 -m conntrack --ctstate ESTABLISHED -j ACCEPTNext, block spoofed packets:
iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROPiptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROPiptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,RST FIN,RST -j DROPiptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROPiptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,URG URG -j DROPiptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,PSH PSH -j DROPiptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROPFinally, block all other incoming traffic:
iptables -t mangle -A PREROUTING -s 224.0.0.0/3 -j DROPiptables -t mangle -A PREROUTING -s 169.254.0.0/16 -j DROPiptables -t mangle -A PREROUTING -s 172.16.0.0/12 -j DROPiptables -t mangle -A PREROUTING -s 192.0.2.0/24 -j DROPiptables -t mangle -A PREROUTING -s 192.168.0.0/16 -j DROPiptables -t mangle -A PREROUTING -s 10.0.0.0/8 -j DROPiptables -t mangle -A PREROUTING -s 0.0.0.0/8 -j DROPiptables -t mangle -A PREROUTING -s 240.0.0.0/5 -j DROPiptables -t mangle -A PREROUTING -s 127.0.0.0/8 ! -i lo -j DROPCertbot
You will need to edit the Nginx configuration file and add your domain name. You can do it with the following command:
sudo nano /etc/nginx/sites-available/defaultEdit each line where it says server_name and replace it with your domain name. Like this:
server { server_name _; # replace with your domain name server_name example.com www.example.com;}Next, you will need to obtain an SSL certificate from Let’s Encrypt. You can do it with the following command:
sudo certbot --nginx -d example.com -d www.example.comReplace example.com with your domain name. You will be asked to provide your email address and accept the terms of service.
Configure Nginx
Next, you will need to configure Nginx to redirect all HTTP traffic to HTTPS. You can do it with the following command:
sudo nano /etc/nginx/sites-available/defaultReplace all the lines with the following lines:
server_tokens off;
server { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri;}
server { listen 443 ssl http2; server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ssl_session_cache shared:SSL:10m; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"; ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"; add_header X-Frame-Options SAMEORIGIN; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; add_header Referrer-Policy "no-referrer-when-downgrade"; add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'"; add_header Permissions-Policy "geolocation=(self), microphone=(), camera=()";
root /var/www/html; index index.html index.htm index.nginx-debian.html;
location / { try_files $uri $uri/ =404; }
location ~ /\.ht { deny all; }
location ~* \.(?:css|gif|htc|ico|jpg|js|png|svg|woff|woff2|otf)$ { expires 1M; access_log off; add_header Cache-Control "public"; }
location ~* \.(?:html|htm|txt)$ { expires 1M; access_log off; add_header Cache-Control "public"; }
location ~* \.(?:ttf|eot)$ { expires 1M; access_log off; add_header Cache-Control "public"; }
location ~* \.(?:xml|rss|svg|svgz|atom)$ { expires 1h; access_log off; add_header Cache-Control "public"; }
location ~* \.(?:js|css)$ { expires 1y; access_log off; add_header Cache-Control "public"; }
location ~* \.(?:json|map)$ { expires 1y; access_log off; add_header Cache-Control "public"; }}Save and close the file when you are finished. Then, test the Nginx configuration with the following command:
sudo nginx -tYou should get the following output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successfulNext, restart the Nginx service to apply the changes:
sudo systemctl restart nginxThank you for reading
In this tutorial, you have learned how to install and secure Nginx on Ubuntu 22.04, 20.04, 18.04 server using Let’s Encrypt and iptables. You can now host your website on your own server.