[{"content":"Objective Configure a Secondary DNS server that automatically replicates DNS zones from the Primary DNS server using zone transfers (AXFR).\nEnvironment Virtualization: VirtualBox OS: ( 1 Primary DNS Server VM + 1 Secondary DNS Server + 1 Web Server VM + 1 Client VM) Network Topology Prerequisites This lab builds upon the following previous labs:\nPrivate DNS Infrastructure with BIND9 Hosting Multiple Websites on One Server Using Nginx The following components are assumed to already be configured:\nBIND9 is installed and running on the DNS server. The forward lookup zone company.lab has already been created. The forward zone file (/etc/bind/db.company.lab) contains the required DNS records. The client is configured to use the internal DNS server (192.168.10.10). DNS resolution between all virtual machines has been verified. The web server hosts multiple virtual websites using Nginx. This lab extends the existing DNS infrastructure by adding a reverse lookup zone.\nPhase 1 - Prepare the Second DNS Server Step 1 - Install BIND9 sudo apt update sudo apt install bind9 bind9-utils dnsutils sudo systemctl status bind9 Step 2 - Verify connectivity ping 192.168.10.10 Step 3 - Check the Port 53 is Listening ss -tulnp | grep :53 Phase 2 - Configure the Primary DNS Server Step 1 - Modify the zone file on primary dns server sudo nano /etc/bind/named.conf.local Step 2 - Verify the Configuration sudo named-checkconf sudo systemctl reload bind9 Phase 3 - Configure the Secondary DNS Server Step 1 - Modify the zone file on secondary dns server sudo nano /etc/bind/named.conf.local Step 2 - Verify the Configuration sudo named-checkconf sudo systemctl restart bind9 Step 3 - Verify the Zone Files ls -l /var/cache/bind/ ","permalink":"https://my-it-blog.netlify.app/posts/secondary-dns-server/","summary":"\u003ch2 id=\"objective\"\u003eObjective\u003c/h2\u003e\n\u003cp\u003eConfigure a Secondary DNS server that automatically replicates DNS zones from the Primary DNS server using zone transfers (AXFR).\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"environment\"\u003eEnvironment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVirtualization: VirtualBox\u003c/li\u003e\n\u003cli\u003eOS: ( 1 Primary DNS Server VM + 1 Secondary DNS Server + 1 Web Server VM + 1 Client VM)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"network-topology\"\u003eNetwork Topology\u003c/h2\u003e\n\u003ch2 id=\"dns-tolopogy\"\u003e\u003cimg alt=\"dns-tolopogy\" loading=\"lazy\" src=\"/posts/secondary-dns-server/topology.png\"\u003e\u003c/h2\u003e\n\u003ch2 id=\"prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cp\u003eThis lab builds upon the following previous labs:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ePrivate DNS Infrastructure with BIND9\u003c/li\u003e\n\u003cli\u003eHosting Multiple Websites on One Server Using Nginx\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe following components are assumed to already be configured:\u003c/p\u003e","title":"Secondary DNS Server"},{"content":"HTTPS with Nginx using a Private Certificate Authority Objective Secure an existing Nginx website using HTTPS and a certificate signed by a private Certificate Authority.\nEnvironment Virtualization: VirtualBox OS: ( 1 DNS Server VM + 1 Web Server VM + 1 Client VM) Network Topology Prerequisites This lab builds upon the Private DNS Infrastructure with BIND9. The following components are assumed to already be configured:\nBIND9 installed and running on the DNS server. The company.lab DNS zone created and configured. The zone file (/etc/bind/db.company.lab) already exists. The client is configured to use the internal DNS server (192.168.10.10) via Netplan. DNS resolution between the client and the DNS server has been verified. Phase 1 - Verify DNS Resolution Before enabling HTTPS, verify that DNS resolves the web server correctly.\nOn the client:\ndig www.company.lab curl http://www.company.lab Phase 2 - Create Certificate Authority Step 1 - Create a directory mkdir ~/ca cd ~/ca Step 2 - Generate CA private key openssl genrsa -out ca.key 4096 Step 3 - Create CA certificate sudo openssl req -x509 -new -nodes \\ -key ca.key \\ -sha256 \\ -days 3650 \\ -out ca.crt Phase 3 - Create the Web Server Private Key On the webserver:\nStep 1 - Create a directory sudo mkdir -p /etc/nginx/ssl cd /etc/nginx/ssl Step 2 - Generate the server\u0026rsquo;s private key sudo openssl genrsa \\ -out www.company.lab.key \\ 2048 Phase 4 - Create Certificate Signing Request (CSR) On the webserver:\nStep 1 - Generate the CSR sudo openssl req -new \\ -key /etc/nginx/ssl/www.company.lab.key \\ -out /etc/nginx/ssl/www.company.lab.csr NOTE: For the fields, we use values similar to the CA, but make the Common Name exactly (www.company.lab)\nPhase 5 - Sign the CSR Step 1 - Copy the CSR to the Certificate Authority On the webserver:\nscp /etc/nginx/ssl/www.company.lab.csr samurai@192.168.10.10:~/ca Step 2 - Sign in on the CA On the DNS server:\ncd ~/ca sudo openssl x509 \\ -in ~/ca/www.company.lab.csr \\ -CA ca.crt \\ -CAkey ca.key \\ -CAcreateserial \\ -out www.company.lab.crt \\ -days 365 \\ -sha256 Phase 6 - Deploy the Certificate Step 1 - Copy the signed certificate back to the webserver scp ~/ca/www.company.lab.crt web-srv@192.168.10.101:/tmp/ Step 2 - On the webserver sudo mv /tmp/www.company.lab.crt /etc/nginx/ssl/ Phase 7 - Configure Nginx Step 1 - Configure Nginx to redirect HTTP traffic to HTTPS and use the signed certificate. sudo nginx -t sudo systemctl reload nginx Phase 8 - Test HTTPS On client:\ncurl -k https://www.company.lab curl http://www.company.lab NOTE: The -k option tells curl to ignore the CA verification.\nPhase 9 - Trust the Certificate Authority Step 1 - Install the CA certificate On DNS server:\nscp /ca/ca.crt client@192.168.10.102:~ On client:\nsudo cp ca.crt \\ /usr/local/share/ca-certificates/company-lab-ca.crt sudo update-ca-certificates Phase 10 - Verify trust Step 1 - Testing https request On client:\ncurl https://www.company.lab Step 2 - Inspect the TLS connection openssl s_client \\ -connect www.company.lab:443 \\ -servername www.company.lab ","permalink":"https://my-it-blog.netlify.app/posts/private-certificate-authority/","summary":"\u003ch1 id=\"https-with-nginx-using-a-private-certificate-authority\"\u003eHTTPS with Nginx using a Private Certificate Authority\u003c/h1\u003e\n\u003ch2 id=\"objective\"\u003eObjective\u003c/h2\u003e\n\u003cp\u003eSecure an existing Nginx website using HTTPS and a certificate signed by a private Certificate Authority.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"environment\"\u003eEnvironment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVirtualization: VirtualBox\u003c/li\u003e\n\u003cli\u003eOS: ( 1 DNS Server VM + 1 Web Server VM + 1 Client VM)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"network-topology\"\u003eNetwork Topology\u003c/h2\u003e\n\u003cp\u003e\u003cimg alt=\"dns-topology\" loading=\"lazy\" src=\"/posts/private-certificate-authority/dns-topology.png\"\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cp\u003eThis lab builds upon the Private DNS Infrastructure with BIND9. The following components are assumed to already be configured:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eBIND9 installed and running on the DNS server.\u003c/li\u003e\n\u003cli\u003eThe company.lab DNS zone created and configured.\u003c/li\u003e\n\u003cli\u003eThe zone file (/etc/bind/db.company.lab) already exists.\u003c/li\u003e\n\u003cli\u003eThe client is configured to use the internal DNS server (192.168.10.10) via Netplan.\u003c/li\u003e\n\u003cli\u003eDNS resolution between the client and the DNS server has been verified.\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"phase-1---verify-dns-resolution\"\u003ePhase 1 - Verify DNS Resolution\u003c/h2\u003e\n\u003cp\u003eBefore enabling HTTPS, verify that DNS resolves the web server correctly.\u003c/p\u003e","title":"HTTPS with Nginx using a Private Certificate Authority"},{"content":"Configuring Reverse DNS (PTR Records) with BIND9 Objective Extend the existing private DNS infrastructure by configuring Reverse DNS (PTR records). This enables IP addresses to be resolved back to hostnames, complementing the forward lookup zone created in previous labs.\nBy the end of this lab, the DNS server will support both:\nForward lookups (hostname → IP address) Reverse lookups (IP address → hostname) Environment Virtualization: VirtualBox OS: ( 1 DNS Server VM + 1 Web Server VM + 1 Client VM) Network Topology Prerequisites This lab builds upon the following previous labs:\nPrivate DNS Infrastructure with BIND9 Hosting Multiple Websites on One Server Using Nginx The following components are assumed to already be configured:\nBIND9 is installed and running on the DNS server. The forward lookup zone company.lab has already been created. The forward zone file (/etc/bind/db.company.lab) contains the required DNS records. The client is configured to use the internal DNS server (192.168.10.10). DNS resolution between all virtual machines has been verified. The web server hosts multiple virtual websites using Nginx. This lab extends the existing DNS infrastructure by adding a reverse lookup zone.\nBackground A forward DNS lookup translates a hostname into an IP address.\nExample:\nwww.company.lab │ ▼ 192.168.10.101\nA reverse DNS lookup performs the opposite operation.\n192.168.10.101 │ ▼ www.company.lab\nReverse DNS uses PTR (Pointer) records instead of A records.\nUnlike forward lookups, reverse lookups are stored in a separate DNS namespace called in-addr.arpa.\nPhase 1 - Configure the Reverse Lookup Zone Step 1 - Edit the BIND configuration sudo nano /etc/bind/named.conf.local NOTE: The DNS server is now authoritative for two independent zones:\ncompany.lab 10.168.192.in-addr.arpa Phase 2 - Create the Reverse Zone File Step 1 - Create a new reverse lookup zone file sudo cp /etc/bind/db.local /etc/bind/db.192.168.10 Phase 3 - Validate the configuration Step 1 - Check the BIND configuration sudo named-checkconf sudo named-checkzone 10.168.192.in-addr.arpa /etc/bind/db.192.168.10 Step 2 - Reload BIND sudo systemctl reload bind9 Phase 4 - Verify Reverse DNS From client:\n","permalink":"https://my-it-blog.netlify.app/posts/reverse-dns/","summary":"\u003ch1 id=\"configuring-reverse-dns-ptr-records-with-bind9\"\u003eConfiguring Reverse DNS (PTR Records) with BIND9\u003c/h1\u003e\n\u003ch2 id=\"objective\"\u003eObjective\u003c/h2\u003e\n\u003cp\u003eExtend the existing private DNS infrastructure by configuring Reverse DNS (PTR records). This enables IP addresses to be resolved back to hostnames, complementing the forward lookup zone created in previous labs.\u003c/p\u003e\n\u003cp\u003eBy the end of this lab, the DNS server will support both:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eForward lookups (hostname → IP address)\u003c/li\u003e\n\u003cli\u003eReverse lookups (IP address → hostname)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"environment\"\u003eEnvironment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVirtualization: VirtualBox\u003c/li\u003e\n\u003cli\u003eOS: ( 1 DNS Server VM + 1 Web Server VM + 1 Client VM)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"network-topology\"\u003eNetwork Topology\u003c/h2\u003e\n\u003cp\u003e\u003cimg alt=\"dns-topology\" loading=\"lazy\" src=\"/posts/reverse-dns/dns-topology.png\"\u003e\u003c/p\u003e","title":"Configuring Reverse DNS (PTR Records) with BIND9"},{"content":"Hosting Multiple Websites on One Server Using Nginx Objective Host multiple websites on a single web server by combining:\nDNS (BIND9) Nginx Virtual Hosts (Server Blocks)\nEnvironment Virtualization: VirtualBox OS: ( 1 DNS Server VM + 1 Web Server VM + 1 Client VM) Network Topology Prerequisites This lab builds upon the Private DNS Infrastructure with BIND9 (3-VM Lab). The following components are assumed to already be configured:\nBIND9 installed and running on the DNS server. The company.lab DNS zone created and configured. The zone file (/etc/bind/db.company.lab) already exists. The client is configured to use the internal DNS server (192.168.10.10) via Netplan. DNS resolution between the client and the DNS server has been verified. In this lab, the existing DNS infrastructure is extended by adding additional DNS records and configuring Nginx virtual hosts to host multiple websites on a single web server.\nPhase 1 - Add DNS Records Step 1 - Edit the Zone file sudo nano /etc/bind/db.company.lab Note: Always increment the SOA serial number after editing the zone file.\nStep 2 - Validate the Zone sudo named-checkzone company.lab /etc/bind/db.company.lab Expected Output: OK\nReload BIND:\nsudo systemctl reload bind9 Phase 2 - Verify DNS From the client:\ndig blog.company.lab A +short dig shop.company.lab A +short dig api.company.lab A +short Expected Output: 192.168.10.101\nPhase 3 - Create Website Directories On the webserver:\nsudo mkdir -p /var/www/www.company.lab sudo mkdir -p /var/www/blog.company.lab sudo mkdir -p /var/www/shop.company.lab sudo mkdir -p /var/www/api.company.lab Create simple home pages:\necho \u0026#34;\u0026lt;h1\u0026gt;Welcome to www.company.lab\u0026lt;/h1\u0026gt;\u0026#34; sudo tee /var/www/www.company.lab/index.html echo \u0026#34;\u0026lt;h1\u0026gt;Welcome to blog.company.lab\u0026lt;/h1\u0026gt;\u0026#34; sudo tee /var/www/blog.company.lab/index.html echo \u0026#34;\u0026lt;h1\u0026gt;Welcome to shop.company.lab\u0026lt;/h1\u0026gt;\u0026#34; sudo tee /var/www/shop.company.lab/index.html echo \u0026#34;\u0026lt;h1\u0026gt;Welcome to api.company.lab\u0026lt;/h1\u0026gt;\u0026#34; sudo tee /var/www/api.company.lab/index.html Phase 4 - Configure Nginx Virtual Hosts Step 1 - Create the Server Block sudo nano /etc/nginx/sites-available/www.company.lab Step 2 - Enable the website sudo ln -s /etc/nginx/sites-available/www.company.lab\\ /etc/nginx/sites-enabled/ Step 3 - Validate the configuration sudo nginx -t Expected outcome: syntax is ok / test is successful\nStep 4 - Reload Nginx sudo systemctl reload nginx Note: Configure the remaining virtual hosts by repeating the Phase 4. Each configuration differs only in two directives (server_name and root)\nPhase 5 - Testing On client:\n","permalink":"https://my-it-blog.netlify.app/posts/nginx-virtual-hosts/","summary":"\u003ch1 id=\"hosting-multiple-websites-on-one-server-using-nginx\"\u003eHosting Multiple Websites on One Server Using Nginx\u003c/h1\u003e\n\u003ch2 id=\"objective\"\u003eObjective\u003c/h2\u003e\n\u003cp\u003eHost multiple websites on a single web server by combining:\u003c/p\u003e\n\u003cp\u003eDNS (BIND9)\nNginx Virtual Hosts (Server Blocks)\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"environment\"\u003eEnvironment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVirtualization: VirtualBox\u003c/li\u003e\n\u003cli\u003eOS: ( 1 DNS Server VM + 1 Web Server VM + 1 Client VM)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"network-topology\"\u003eNetwork Topology\u003c/h2\u003e\n\u003cp\u003e\u003cimg alt=\"dns-topology\" loading=\"lazy\" src=\"/posts/nginx-virtual-hosts/dns_vhost_topology.png\"\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cp\u003eThis lab builds upon the Private DNS Infrastructure with BIND9 (3-VM Lab). The following components are assumed to already be configured:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eBIND9 installed and running on the DNS server.\u003c/li\u003e\n\u003cli\u003eThe company.lab DNS zone created and configured.\u003c/li\u003e\n\u003cli\u003eThe zone file (/etc/bind/db.company.lab) already exists.\u003c/li\u003e\n\u003cli\u003eThe client is configured to use the internal DNS server (192.168.10.10) via Netplan.\u003c/li\u003e\n\u003cli\u003eDNS resolution between the client and the DNS server has been verified.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eIn this lab, the existing DNS infrastructure is extended by adding additional DNS records and configuring Nginx virtual hosts to host multiple websites on a single web server.\u003c/p\u003e","title":"Hosting Multiple Websites on One Server Using Nginx"},{"content":"Private DNS Infrastructure with BIND9 Objective Build a private DNS infrastructure using BIND9 where:\nA DNS server resolves names in the company.lab domain. A web server hosts a website. A client uses the DNS server to locate and access the web server. Environment Virtualization: VirtualBox OS: ( 1 DNS Server VM + 1 Web Server VM + 1 Client VM) Network Topology Phase 1 - Configure DNS Server Step 1 - Install BIND9 and verify sudo apt update sudo apt install bind9 bind9-utils dnsutils sudo systemctl status named/bind9 ss -tulnp | grep 192.168.10.10:53 Step 2 - Create DNS Zone sudo nano /etc/bind/named.conf.local Step 3 - Create Zone file sudo cp /etc/bind/db.local /etc/bind/db.company.lab sudo nano /etc/bind/db.company.lab Step 4 - Validate configuration and zone sudo named-checkconf Expected: no output\nsudo named-checkzone company.lab /etc/bind/db.company.lab Expected: OK\nReload BIND:\nsudo systemctl reload bind9 Step 5 - Test DNS Server dig @localhost www.company.lab Phase 2 - Configure Web Server Step 1 - Install Nginx sudo apt update sudo apt install nginx sudo systemctl status nginx Phase 3 - Configure Client Step 1 - Edit netplan: sudo nano /etc/netplan/01-netcfg.yaml sudo netplan apply Step 2 - Verify DNS resolution resolvectl status Step 3 - Test dig www.company.lab curl http://www.company.lab ping -c4 www.company.lab ","permalink":"https://my-it-blog.netlify.app/posts/private-dns/","summary":"\u003ch1 id=\"private-dns-infrastructure-with-bind9\"\u003ePrivate DNS Infrastructure with BIND9\u003c/h1\u003e\n\u003ch2 id=\"objective\"\u003eObjective\u003c/h2\u003e\n\u003cp\u003eBuild a private DNS infrastructure using BIND9 where:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eA DNS server resolves names in the company.lab domain.\u003c/li\u003e\n\u003cli\u003eA web server hosts a website.\u003c/li\u003e\n\u003cli\u003eA client uses the DNS server to locate and access the web server.\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"environment\"\u003eEnvironment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVirtualization: VirtualBox\u003c/li\u003e\n\u003cli\u003eOS: ( 1 DNS Server VM + 1 Web Server VM + 1 Client VM)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"network-topology\"\u003eNetwork Topology\u003c/h2\u003e\n\u003cp\u003e\u003cimg alt=\"dns-topology\" loading=\"lazy\" src=\"/posts/private-dns/dns-topology.png\"\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"phase-1---configure-dns-server\"\u003ePhase 1 - Configure DNS Server\u003c/h2\u003e\n\u003ch3 id=\"step-1---install-bind9-and-verify\"\u003eStep 1 - Install BIND9 and verify\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt update\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt install bind9 bind9-utils dnsutils\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl status named/bind9\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ess -tulnp | grep 192.168.10.10:53\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"bind9-status\" loading=\"lazy\" src=\"/posts/private-dns/bind9-status.png\"\u003e\n\u003cimg alt=\"verify\" loading=\"lazy\" src=\"/posts/private-dns/verify-bind.png\"\u003e\u003c/p\u003e","title":"Private DNS Infrastructure with BIND9"},{"content":"Objective The lab focuses on troubleshooting real-world network failures by systematically isolating issues at each layer of the network stack.\nNetwork Topology LAN (User Network)\tDMZ (Service Network) 192.168.10.0/24\t192.168.20.0/24 __________________\t_____________________ Client VM\tServer VM 192.168.10.101\t192.168.20.10 |\t| |\t| ________ Firewall VM ___________ (Router + Firewall) Issue 1: No connectivity between networks Failure to connect to the webserver\nTroubleshooting Workflow Step 1 - Verify the service exists From Server:\nss -tuln | grep :8080 QUESTION: Is the application listening? NO -\u0026gt; Problem in application layer YES -\u0026gt; Continue\nStep 2 - Verify local connectivity From Firewall:\ncurl http://192.168.20.10:8080 QUESTION: Can the firewall reach the server? NO -\u0026gt; Routing/Interface problem YES -\u0026gt; Server \u0026amp; DMZ network are working. (Continue)\nStep 3 - Verify packet arrival On firewall:\nsudo tcpdump -i enp0s8 tcp port 8080 On client:\ncurl http://192.168.20.20:8080 !(enp0s8)[enp0s8.png]\nQUESTION: Does traffic reach the firewall? NO -\u0026gt; Client routing issue, Wrong gateway, Wrong subnet YES -\u0026gt; Client-Firewall network works correctly (Continue)\nStep 4 - Verify packet forwarding On firewall:\nsudo tcpdump -i enp0s9 tcp port 8080 On client:\ncurl http://192.168.20.20:8080 !(enp0s9)[enp0s9.png]\nQUESTION: Does the traffic leave the firewall? NO -\u0026gt; Problem exists INSIDE firewall forwarding path: ip_forward is disabled, nftables is dropping packets, routing table issue (Continue) YES -\u0026gt; Problem is likely: return path, server firewall, application\nStep 5 - Verify kernel forwarding sysctl net.ipv4.ip_forward ROOT CAUSE FOUND\nsudo sysctl -w net.ipv4.ip_forward=1 OR\nsudo nano /etc/sysctl.d/99-sysctl.conf net.ipv4.ip_forward=1 sudo sysctl --system Step 6 - Verify From client:\ncurl http://192.168.20.10:8080 Issue 2: Server reachable from firewall but not client Troubleshooting Workflow Step 1 - Verify the service exists From Server:\nss -tuln | grep :8080 QUESTION: Is the application listening? NO -\u0026gt; Problem in application layer YES -\u0026gt; Continue\nStep 2 - Verify local connectivity From firewall:\ncurl http://192.168.20.10:8080 QUESTION: Can the firewall reach the server? NO -\u0026gt; Routing/Interface problem YES -\u0026gt; Server \u0026amp; DMZ network are working. (Continue)\nStep 3 - Verify packet arrival On firewall:\nsudo tcpdump -i enp0s8 tcp port 8080 On client:\ncurl http://192.168.20.10:8080 QUESTION: Does traffic reach the firewall? NO -\u0026gt; Client routing issue, Wrong gateway, Wrong subnet YES -\u0026gt; Client-Firewall network works correctly (Continue)\nStep 4 - Verify packet forwarding On firewall:\nsudo tcpdump -i enp0s9 tcp port 8080 On client:\ncurl http://192.168.20.20:8080 QUESTION: Does the traffic leave the firewall? NO -\u0026gt; Problem exists INSIDE firewall forwarding path: ip_forward is disabled, nftables is dropping packets, routing table issue (Continue) YES -\u0026gt; Problem is likely: return path, server firewall, application\nStep 5 - Verify kernel forwarding sysctl net.ipv4.ip_forward Step 6 - Check nftables behavior sudo nft list ruleset ROOT CAUSE: The firewall is dropping all forwarded traffic because no FORWARD chain rules exist to explicitly allow LAN → DMZ communication.\nFIX:\nsudo nft add rule inet filter forward ct state established,related accept sudo nft add rule inet filter forward iif enp0s8 oif enp0s9 sudo nft add rule inet filter forward ip saddr 192.168.10.101 ip daddr 192.168.20.10 tcp port 8080 accept Step 7 - Verify From client:\ncurl http://192.168.20.10:8080 ","permalink":"https://my-it-blog.netlify.app/posts/dmz-networking/","summary":"\u003ch2 id=\"objective\"\u003eObjective\u003c/h2\u003e\n\u003cp\u003eThe lab focuses on troubleshooting real-world network failures by systematically isolating issues at each layer of the network stack.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"network-topology\"\u003eNetwork Topology\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eLAN (User Network)\t\tDMZ (Service Network)\n192.168.10.0/24\t\t\t192.168.20.0/24\n__________________\t\t_____________________\n\nClient VM\t\t\tServer VM\n192.168.10.101\t\t\t192.168.20.10\n\t|\t\t\t\t|\n\t|\t\t\t\t|\n\t________ Firewall VM ___________\n\t\t(Router + Firewall)\n\u003c/code\u003e\u003c/pre\u003e\u003chr\u003e\n\u003ch2 id=\"issue-1-no-connectivity-between-networks\"\u003eIssue 1: No connectivity between networks\u003c/h2\u003e\n\u003cp\u003eFailure to connect to the webserver\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"issue\" loading=\"lazy\" src=\"/posts/dmz-networking/issue.png\"\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"troubleshooting-workflow\"\u003eTroubleshooting Workflow\u003c/h2\u003e\n\u003ch3 id=\"step-1---verify-the-service-exists\"\u003eStep 1 - Verify the service exists\u003c/h3\u003e\n\u003cp\u003eFrom Server:\u003c/p\u003e","title":"Linux Firewall \u0026 DMX Networking Lab"},{"content":"Objective The goal of this lab is to design and implement a basic DMZ (Demilitarized Zone) network using Linux virtual machines, understand routing between network segments, and apply nftables as a stateful firewall.\nNetwork Topology LAN (User Network)\tDMZ (Service Network) 192.168.10.0/24\t192.168.20.0/24 __________________\t_____________________ Client VM\tServer VM 192.168.10.101\t192.168.20.10 |\t| |\t| ________ Firewall VM ___________ (Router + Firewall) VM \u0026amp; Routing Configuration Client VM sudo netplan try sudo netplan apply Firewall VM (Core Router) sudo netplan try sudo netplan apply The Firewall MUST ENABLE packet forwarding:\nTemporary enable:\nsudo sysctl -w net.ipv4.ip_forward=1 Permanent enable:\necho \u0026#34;net.ipv4.ip_forward=1\u0026#34; | sudo tee /etc/sysctl.d/99-ipforward.conf sudo sysctl --system Server VM (DMZ Host) sudo netplan try sudo netplan apply nftables Firewall Configuration Step 1 - Create table sudo nft add table inet filter Step 2 - Create FORWARD chain (core DMZ control point) sudo nft add chain inet filter forward \\ \u0026#39;{ type filter hook forward priority 0; policy drop; }\u0026#39; Step 3 - Allow return traffic (stateful firewall behavior) sudo nft add rule inet filter forward \\ ct state established,related accept iif enp0s8 oif enp0s9 Step 4 - Allow LAN -\u0026gt; DMZ HTTP access (TCP 8080) sudo nft add rule inet filter forward \\ ip saddr 192.168.10.101 \\ ip daddr 192.168.20.10 \\ tcp dport 8080 accept Services Used On Server VM:\npython3 -m http.server 8080 \u0026amp; This simulates a simple HTTP service.\nTesting LAN to DMZ connectivity (HTTP) From Client VM:\ncurl http://192.168.20.10:8080 From Server VM:\nFirewall verification Check packet flow:\nsudo tcpdump -i enp0s8 sudo tcpdump -i enp0s9 Expected:\nRequests visible on enp0s8 Forwarded traffic visible on enp0s9 ","permalink":"https://my-it-blog.netlify.app/posts/dmz/","summary":"\u003ch2 id=\"objective\"\u003eObjective\u003c/h2\u003e\n\u003cp\u003eThe goal of this lab is to design and implement a basic DMZ (Demilitarized Zone) network using Linux virtual machines, understand routing between network segments, and apply nftables as a stateful firewall.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"network-topology\"\u003eNetwork Topology\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eLAN (User Network)\t\tDMZ (Service Network)\n192.168.10.0/24\t\t\t192.168.20.0/24\n__________________\t\t_____________________\n\nClient VM\t\t\tServer VM\n192.168.10.101\t\t\t192.168.20.10\n\t|\t\t\t\t|\n\t|\t\t\t\t|\n\t________ Firewall VM ___________\n\t\t(Router + Firewall)\n\u003c/code\u003e\u003c/pre\u003e\u003chr\u003e\n\u003ch2 id=\"vm--routing-configuration\"\u003eVM \u0026amp; Routing Configuration\u003c/h2\u003e\n\u003ch3 id=\"client-vm\"\u003eClient VM\u003c/h3\u003e\n\u003cp\u003e\u003cimg alt=\"client-config\" loading=\"lazy\" src=\"/posts/dmz/client-conf.png\"\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo netplan try\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo netplan apply\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"firewall-vm-core-router\"\u003eFirewall VM (Core Router)\u003c/h3\u003e\n\u003cp\u003e\u003cimg alt=\"firewall-config\" loading=\"lazy\" src=\"/posts/dmz/frw-conf.png\"\u003e\u003c/p\u003e","title":"DMZ Network Lab - Firewall, Routing, and nftables"},{"content":"Objective Lab Environment Client VM 1 - 192.168.10.101 Client VM 2 - 192.168.10.102 Server VM - 192.168.10.10\nServer Setup Step 1 - Run web server python3 -m http.server 8080 ss -tln | grep :8080 Step 2 - Base firewall configuration sudo nft add table inet filter sudo nft add chain inet filter input \\ \u0026#39;{ type filter hook input priority 0; policy drop; }\u0026#39; sudo nft add rule inet filter input iif lo accept sudo nft add rule inet filter input ct state established,related accept Practical Task 1 Objective - Understand how a stateful firewall allows packets belonging to existing connections.\nStep 1 - Add SSH rule sudo nft add rule inet filter input tcp dport 22 accept Step 2 - Connect from Client VM ssh user@SERVER_IP Step 3 - Delete SSH rule sudo nft -a list ruleset sudo nft delete rule inet filter input handle 4 Expected Result:\nCurrent SSH session - Works (matches ct state established,related accept) New SSH session - Blocked (does not match any rule and it\u0026rsquo;s dropped)\nPractical Task 2 Objective - Allow access to a web service based on destination port.\nStep 1 - Add HTTP rule sudo nft add rule inet filter input tcp dport 8080 accept From Client VM:\ncurl http://192.168.10.10:8080 Expected Result: HTML page returned\nEXPERIMENT\nStep 2 - Replace HTTP rule sudo nft replace rule inet filter input handle 5 tcp dport 8080 drop From Client VM:\ncurl http://192.168.10.10:8080 Expected Result: Connection timed out\nIMPORTANT OBSERVATION\nServer process is still running:\nCONCEPT: Listening service ≠ Reachable service (The firewall decides reachability)\nPractical Task 3 - Source IP Filtering Objective - Allow only a specific client to access the web server.\nStep 1 - Configuration sudo nft add rule inet filter input ip saddr 192.168.10.101 tcp dport 8080 accept sudo nft add rule inet filter input tcp dport 8080 drop sudo nft add rule inet filter input log prefix \\\u0026#34;DROP: \\\u0026#34; Step 2 - Verification Run on Client VM 1 and Client VM 2:\ncurl http://192.168.10.10:8080 Run on Server VM:\njournalctl -f CONCEPT: ACL (Access Control Lists) Traffic can be filtered not only by port but also by source address\n","permalink":"https://my-it-blog.netlify.app/posts/nftables/","summary":"\u003ch2 id=\"objective\"\u003eObjective\u003c/h2\u003e\n\u003chr\u003e\n\u003ch2 id=\"lab-environment\"\u003eLab Environment\u003c/h2\u003e\n\u003cp\u003eClient VM 1 - 192.168.10.101\nClient VM 2 - 192.168.10.102\nServer VM - 192.168.10.10\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"server-setup\"\u003eServer Setup\u003c/h2\u003e\n\u003ch3 id=\"step-1---run-web-server\"\u003eStep 1 - Run web server\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython3 -m http.server \u003cspan style=\"color:#ae81ff\"\u003e8080\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ess -tln | grep :8080\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"web-server\" loading=\"lazy\" src=\"/posts/nftables/web-server.png\"\u003e\u003c/p\u003e\n\u003ch3 id=\"step-2---base-firewall-configuration\"\u003eStep 2 - Base firewall configuration\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nft add table inet filter\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nft add chain inet filter input \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;{ type filter hook input priority 0; policy drop; }\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nft add rule inet filter input iif lo accept\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nft add rule inet filter input ct state established,related accept\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"ruleset\" loading=\"lazy\" src=\"/posts/nftables/basenft_ruleset.png\"\u003e\u003c/p\u003e","title":"Linux nftables Firewall Fundamentals Lab"},{"content":"Objective This lab demonstrates how Linux Full Disk Encryption (LUKS) works and what it protects against.\nPart 1 - Attack Scenario (Unencrypted Disk) Step 1 - Identify disk lsblk Step 2 - Create filesystem (no ecnryption) sudo mkfs.ext4 /dev/sdc Step 3 - Mount disk sudo mkdir /mnt/test sudo mount /dev/sdc /mnt/test Step 4 - Add sensitive data echo \u0026#34;Sensitive data\u0026#34; | sudo tee /mount/test/secret.txt ATTACK SIMULATION Step 1 - Direct mount attempt sudo mkdir /mnt/attack; sudo mount /dev/sdc /mnt/attack ls -l /mnt/attack cat /mnt/attack/secret.txt Part 2 - LUKS Encryption Setup (Defense) Step 1 - Identify target disk lsblk Find: target -\u0026gt; sdb (2.9G)\nStep 2 - Initialize LUKS encryption sudo cryptsetup luksFormat /dev/sdb Step 3 - Unlock encrypted disk sudo cryptsetup luksOpen /dev/sdb secure_disk ls /dev/mapper This creates: /dev/mapper/secure_disk\nStep 4 - Create filesystem sudo mkfs.ext4 /dev/mapper/secure_disk Step 5 - Mount filesystem sudo mkdir /mnt/secure sudo mount /dev/mapper/secure_disk /mnt/secure Step 6 - Store secret data echo \u0026#34;TOP SECRET DATA\u0026#34; | sudo tee /mnt/secure/secure/secret.txt Step 7 - Unmount filesystem and close encrypted disk sudo umount /mnt/secure sudo cryptsetup luksClose secure_disk Part 3 - Attack against LUKS Disk Attacker steals /dev/sdb\nStep 1 - Try direct mount sudo mkdir /mnt/attack2; sudo mount /dev/sdb /mnt/attack2 Step 2 - Try unlocking encrypted disk sudo cryptsetup luksOpen /dev/sdb Part 4 - Legitimate Unlock Process Step 1 - Unlock disk sudo cryptsetup luksOpen /dev/sdb secure_disk Enter passphrase.\nStep 2 - Mount sudo mount /dev/mapper/secure_disk /mnt/secure Step 3 - Read data cat /mnt/secure/secret.txt Key Security Insight LUKS protects:\nData at rest Stolen disks Offline attacks LUKS does NOT protect:\nAlready-unlocked system Root user after login Weak passphrases RAM extraction attacks ","permalink":"https://my-it-blog.netlify.app/posts/luks-encryption-lab/","summary":"\u003ch3 id=\"objective\"\u003eObjective\u003c/h3\u003e\n\u003cp\u003eThis lab demonstrates how Linux Full Disk Encryption (LUKS) works and what it protects against.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"part-1---attack-scenario-unencrypted-disk\"\u003ePart 1 - Attack Scenario (Unencrypted Disk)\u003c/h2\u003e\n\u003ch3 id=\"step-1---identify-disk\"\u003eStep 1 - Identify disk\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elsblk\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"step-2---create-filesystem-no-ecnryption\"\u003eStep 2 - Create filesystem (no ecnryption)\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo mkfs.ext4 /dev/sdc\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"sdc\" loading=\"lazy\" src=\"/posts/luks-encryption-lab/sdc.png\"\u003e\u003c/p\u003e\n\u003ch3 id=\"step-3---mount-disk\"\u003eStep 3 - Mount disk\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo mkdir /mnt/test\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo mount /dev/sdc /mnt/test\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"mount_sdc\" loading=\"lazy\" src=\"/posts/luks-encryption-lab/mount_sdc.png\"\u003e\u003c/p\u003e\n\u003ch3 id=\"step-4---add-sensitive-data\"\u003eStep 4 - Add sensitive data\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Sensitive data\u0026#34;\u003c/span\u003e | sudo tee /mount/test/secret.txt\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"attack-simulation\"\u003eATTACK SIMULATION\u003c/h2\u003e\n\u003ch3 id=\"step-1---direct-mount-attempt\"\u003eStep 1 - Direct mount attempt\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo mkdir /mnt/attack; sudo mount /dev/sdc /mnt/attack\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003els -l /mnt/attack\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecat /mnt/attack/secret.txt\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"exposed_data\" loading=\"lazy\" src=\"/posts/luks-encryption-lab/attack1_exposed_data.png\"\u003e\u003c/p\u003e","title":"LUKS Full Disk Encryption Lab (Attack \u0026 Defense)"},{"content":"Attack Simulation: Gaining Root Access via GRUB Objective Demonstrate how physical access to a Linux system can be abused to gain root privileges by modifying GRUB boot parameters.\nPrerequisites OS: Linux Ubuntu Access to GRUB menu during boot No GRUB password protection enabled Attack Steps Reboot the system and access the GRUB menu. Select the default Linux entry and press e to edit boot parameters. Locate the line starting with: linux /boot/vmlinuz-\u0026hellip; Modify the line Boot the modified entry using Ctrl + X Result The system boots into rescue mode or a root shell Authentication is bypassed Attacker obtains root-level access before login Defense: GRUB Hardening Using Password Protection Objective Prevent unauthorized modification of boot parameters by securing GRUB with a password.\nStep 1: Generate a GRUB Password Hash sudo apt update sudo apt install grub-common grub-mkpasswd-pbkdf2 Step 2 - Configure GRUB User Authentication sudo nano /etc/grub.d/40-custom Step 3 - Apply Configuration sudo update-grub Step 4 - Reboot and Test sudo reboot Pressing SHIFT to enter GRUB menu\nResult after Hardening Boot parameter editing is blocked without authentication Kernel-level attack methods are prevented Conclusion GRUB password protection is an essential security layer that prevents:\nBoot parameter manipulation Unauthorized rescue mode access Root shell injection via kernel arguments However, it should be combined with:\nFull disk encryption (LUKS) BIOS/UEFI security Secure boot configuration to fully protect against physical attacks.\n","permalink":"https://my-it-blog.netlify.app/posts/grub-security-lab/","summary":"\u003ch2 id=\"attack-simulation-gaining-root-access-via-grub\"\u003eAttack Simulation: Gaining Root Access via GRUB\u003c/h2\u003e\n\u003ch3 id=\"objective\"\u003eObjective\u003c/h3\u003e\n\u003cp\u003eDemonstrate how physical access to a Linux system can be abused to gain root privileges by modifying GRUB boot parameters.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eOS: Linux Ubuntu\u003c/li\u003e\n\u003cli\u003eAccess to GRUB menu during boot\u003c/li\u003e\n\u003cli\u003eNo GRUB password protection enabled\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"attack-steps\"\u003eAttack Steps\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eReboot the system and access the GRUB menu.\u003c/li\u003e\n\u003cli\u003eSelect the default Linux entry and press e to edit boot parameters.\u003c/li\u003e\n\u003cli\u003eLocate the line starting with: linux /boot/vmlinuz-\u0026hellip;\u003c/li\u003e\n\u003cli\u003eModify the line\u003c/li\u003e\n\u003cli\u003eBoot the modified entry using Ctrl + X\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cimg alt=\"grub_systemd\" loading=\"lazy\" src=\"/posts/grub-security-lab/grub_systemd.png\"\u003e\u003c/p\u003e","title":"GRUB Security Lab: Boot-Time Privilege Escalation \u0026 Hardening"},{"content":"Objective Setting up automatic USB drive mounting on a Linux server using systemd mount and automount units\nEnvironment OS: Ubuntu Tools: system, USB drive Step 1 - Find Partition UUID Prerequisite: Plugin USB drive\nblkid /dev/sdb1 Note: UUID and filesystem type\nStep 2 - Create the Mount Unit sudo nano /etc/systemd/system/mnt-usb.mount Step 3 - Create Automount Unit sudo nano /etc/systemd/system/mnt-usb.automount Step 4 - Enable and Start sudo systemctl enable mnt-usb.automount sudo systemctl start mnt-usb.automount Step 5 - Verify and test Check the automount is active:\nsystemctl status mnt-usb.automount Trigger the mount by accessing the path:\nls -l /mnt/usb Verify it\u0026rsquo;s mounted:\nlsblk mount | grep usb ","permalink":"https://my-it-blog.netlify.app/posts/usb-automounting/","summary":"\u003ch2 id=\"objective\"\u003eObjective\u003c/h2\u003e\n\u003cp\u003eSetting up automatic USB drive mounting on a Linux server using systemd mount and automount units\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"environment\"\u003eEnvironment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eOS: Ubuntu\u003c/li\u003e\n\u003cli\u003eTools: system, USB drive\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"step-1---find-partition-uuid\"\u003eStep 1 - Find Partition UUID\u003c/h2\u003e\n\u003cp\u003ePrerequisite: Plugin USB drive\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eblkid /dev/sdb1\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"sdb1\" loading=\"lazy\" src=\"/posts/usb-automounting/sdb1.png\"\u003e\u003c/p\u003e\n\u003cp\u003eNote: UUID and filesystem type\u003c/p\u003e\n\u003ch2 id=\"step-2---create-the-mount-unit\"\u003eStep 2 - Create the Mount Unit\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nano /etc/systemd/system/mnt-usb.mount\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"mnt-usb.mount\" loading=\"lazy\" src=\"/posts/usb-automounting/mnt-usb_mount.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"step-3---create-automount-unit\"\u003eStep 3 - Create Automount Unit\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nano /etc/systemd/system/mnt-usb.automount\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"mnt-usb.automount\" loading=\"lazy\" src=\"/posts/usb-automounting/mnt-usb_automount.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"step-4---enable-and-start\"\u003eStep 4 - Enable and Start\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl enable mnt-usb.automount\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl start mnt-usb.automount\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"step-5---verify-and-test\"\u003eStep 5 - Verify and test\u003c/h2\u003e\n\u003cp\u003eCheck the automount is active:\u003c/p\u003e","title":"USB Automounting with systemd"},{"content":"Objective Build a centralized logging environment where:\nSERVER receives logs from client1 SERVER receives logs from client2 Logs are stored in separate files: /var/log/client1.log /var/log/client2.log Network Layout Host IP server 192.168.10.10 client1 192.168.10.101 client2 192.168.10.102 Environment OS: Ubuntu Tools: rsyslog Part 1 - Configure the rsyslog Server Verify rsyslog sudo systemctl status rsyslog Enable UDP Syslog reception and restart the rsyslog service sudo nano /etc/rsyslog.conf sudo systemctl restart rsyslog Verify server is listening on port 514 ss -ulnp | grep 514 Part 2 - Separate logs by Client sudo nano /etc/rsyslog.d/30-multi-client.conf sudo systemctl restart rsyslog Part 3 - Configure Client1 and Client2 sudo nano /etc/rsyslog.d/10-remote.conf sudo systemctl restart rsyslog Part 4 - Test Log Delivery from Client1:\nlogger -t CLIENT1 \u0026#34;hello from Client1\u0026#34; from Client2:\nlogger -t CLIENT2 \u0026#34;hello from Client2\u0026#34; from Server:\ntail -n 10 /var/log/client1.log | grep -a \u0026#34;hello\u0026#34; tail -n 10 /var/log/client1.log | grep -a \u0026#34;hello\u0026#34; ","permalink":"https://my-it-blog.netlify.app/posts/rsyslog-centralized-logging/","summary":"\u003ch2 id=\"objective\"\u003eObjective\u003c/h2\u003e\n\u003cp\u003eBuild a centralized logging environment where:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eSERVER receives logs from client1\u003c/li\u003e\n\u003cli\u003eSERVER receives logs from client2\u003c/li\u003e\n\u003cli\u003eLogs are stored in separate files:\n\u003cul\u003e\n\u003cli\u003e/var/log/client1.log\u003c/li\u003e\n\u003cli\u003e/var/log/client2.log\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"network-layout\"\u003eNetwork Layout\u003c/h2\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003eHost\u003c/th\u003e\n          \u003cth\u003eIP\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eserver\u003c/td\u003e\n          \u003ctd\u003e192.168.10.10\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eclient1\u003c/td\u003e\n          \u003ctd\u003e192.168.10.101\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eclient2\u003c/td\u003e\n          \u003ctd\u003e192.168.10.102\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"environment\"\u003eEnvironment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eOS: Ubuntu\u003c/li\u003e\n\u003cli\u003eTools: rsyslog\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"part-1---configure-the-rsyslog-server\"\u003ePart 1 - Configure the rsyslog Server\u003c/h2\u003e\n\u003ch3 id=\"verify-rsyslog\"\u003eVerify rsyslog\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl status rsyslog\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"rsyslog_status\" loading=\"lazy\" src=\"/posts/rsyslog-centralized-logging/server_rsyslog_status.png\"\u003e\u003c/p\u003e\n\u003ch3 id=\"enable-udp-syslog-reception-and-restart-the-rsyslog-service\"\u003eEnable UDP Syslog reception and restart the rsyslog service\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nano /etc/rsyslog.conf\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl restart rsyslog\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"udp_enabled\" loading=\"lazy\" src=\"/posts/rsyslog-centralized-logging/udp_enabled.png\"\u003e\u003c/p\u003e","title":"Centralized rsyslog server"},{"content":"🧪 DNS Lab 📌 Objective Understand DNS from a systems perpective\n⚙️ Environment Virtualization: VirtualBox OS: ( 1 DNS Server VM + 1 Client VM) 🛠️ Lab Network Topology 🧩 Phase 1 — Direct DNS (No Cache) Client VM -\u0026gt; dnsmasq (192.168.10.10)\nUsed for:\nBreak #1 (Wrong DNS Server) Break #2 (Wrong DNS Record) 🧩 Phase 2 — Direct DNS (No Cache) Clint VM -\u0026gt; systemd-resolved (127.0.0.53) [CACHE] -\u0026gt; dnsmasq (192.168.10.10) [DNS SERVER]\nUsed for:\nBreak #3 (DNS Caching Behavior) ⚙️ Part 1 — DNS Server Setup (dnsmasq) Step 1 - Install sudo apt install dnsmasq Step 2 - Configure domain mapping sudo nano /etc/dnsmasq.conf Step 3 - Start service sudo systemctl restart dnsmasq sudo systemctl status dnsmasq Step 4 - Test locally dig @127.0.0.1 myapp.local Expected result: myapp.local -\u0026gt; 192.168.10.10\n⚙️ Part 2 — Client Setup (Phase 1: No cache) Client sends queries directly to dnsmasq.\nClient -\u0026gt; dnsmasq\nStep 1 - Configure resolver manually sudo nano /etc/resolv.conf Step 2 - Test dig myapp.local ping myapp.local Break 1 - Wrong DNS Server Change resolver\nsudo nano /etc/resolv.conf Observed behavior dig myapp.local -\u0026gt; communications error to 8.8.8.8#53, timed out ping -\u0026gt; temporary failure in name resolution ping 192.168.10.10 -\u0026gt; ✅ works Interpetation DNS query sent to wrong server\n🧠 Root Cause Client resolver misconfigured\n🔧 Fix Change the resolver config:\nnameserver 192.168.10.10 Break 2 - Wrong DNS Record Misconfigure dnsmasq.conf\nsudo nano /etc/dnsmasq.conf sudo systemctl restart dnsmasq Observed behavior Run from client VM:\ndig myapp.local -\u0026gt; 192.168.10.99 ping myapp.local -\u0026gt; fails (Destination Host Unreachable) ping 192.168.10.10 -\u0026gt; ✅ works Interpretation DNS works but returns incorrect IP\n🧠 Root Cause Conclusion: dnsmasq is misconfigured\n🔧 Fix Change the dnsmasq.conf:\naddress=/myapp.local/192.168.10.10 Break 3 - Cached DNS ⚙️ Setup Step 1: Enable caching on client vm:\nsudo systemctl enable --now systemd-resolved sudo ln -sf /run/system/resolve/stub-resolv.conf /etc/resolv.conf sudo resolvectl dns enp0s8 192.168.10.10 Step 2: Configure server dnsmasq.conf: address=/myapp.local/192.168.10.99 local-ttl=60 cache-size=1000 sudo systemctl restart dnsmasq Observed behavior On client VM:\nsudo resolvectl query myapp.local Interpretation Client cache used instead of querying DNS\n🧠 Root Cause TTL not expired -\u0026gt; cached response\n🔧 Fix sudo resolvectl flush-caches ","permalink":"https://my-it-blog.netlify.app/posts/dns-server/","summary":"\u003ch1 id=\"-dns-lab\"\u003e🧪 DNS Lab\u003c/h1\u003e\n\u003ch2 id=\"-objective\"\u003e📌 Objective\u003c/h2\u003e\n\u003cp\u003eUnderstand DNS from a systems perpective\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-environment\"\u003e⚙️ Environment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVirtualization: VirtualBox\u003c/li\u003e\n\u003cli\u003eOS: ( 1 DNS Server VM + 1 Client VM)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"-lab-network-topology\"\u003e🛠️ Lab Network Topology\u003c/h2\u003e\n\u003ch3 id=\"-phase-1--direct-dns-no-cache\"\u003e🧩 Phase 1 — Direct DNS (No Cache)\u003c/h3\u003e\n\u003cp\u003eClient VM -\u0026gt; dnsmasq (192.168.10.10)\u003c/p\u003e\n\u003cp\u003eUsed for:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eBreak #1 (Wrong DNS Server)\u003c/li\u003e\n\u003cli\u003eBreak #2 (Wrong DNS Record)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch3 id=\"-phase-2--direct-dns-no-cache\"\u003e🧩 Phase 2 — Direct DNS (No Cache)\u003c/h3\u003e\n\u003cp\u003eClint VM -\u0026gt; systemd-resolved (127.0.0.53) [CACHE] -\u0026gt; dnsmasq (192.168.10.10) [DNS SERVER]\u003c/p\u003e","title":"DNS Lab - Dnsmasq, Client resolver, Caching"},{"content":"🧪 Inter-Interface Packet Forwarding Failure Investigation 📌 Objective Diagnose why a client cannot reach the internet\n⚙️ Environment Virtualization: VirtualBox OS: ( 1 DHCP Server VM + 1 Client VM) 🛠️ Lab Network Topology Server (DHCP)\nIP: 192.168.10.10 Interfaces: enp0s8 -\u0026gt; LAN enp0s3 -\u0026gt; NAT Client VM\nIP: 192.168.10.100 Interface: enp0s8 Gateway: 192.168.10.10 🚨 Incident Statement Client cannot access the internet\n🔍 PHASE 1 — Verify the Problem Run on Client VM:\nping -c 2 192.168.10.10 ping -c 2 8.8.8.8 Expected outcome:\nGateway ping -\u0026gt; ✅ works Internet ping -\u0026gt; ❌ fails Conclusion:\nLocal network works -\u0026gt; L2 is OK Internet fails -\u0026gt; issue beyond local network PHASE 2 — Check Client Configuration ip a ip route Conclusion:\nClient is correctly configured Traffic is sent to gateway PHASE 3 - Verify L2 Step 1 - Check ARP Run on client VM:\nip neigh Expected outcome: 192.168.10.10 dev enp0s8 lladdr: XX:XX:XX:XX STALE\nStep 2 - Capture ARP Run on client VM:\nsudo tcpdump -i enp0s8 arp ping 192.168.10.10 Conclusion:\nARP works -\u0026gt; MAC resolution works L2 is fully functional Phase 4 - Follow the packet Step 1 - Capture incoming traffic On server:\nsudo tcpdump -i enp0s8 icmp On client:\nping 8.8.8.8 Expected outcome:\nPackets arrive at server (enp0s8) Step 2 - Check outgoing traffic\nOn server:\nsudo tcpdump -i enp0s3 icmp Expected outcome:\nNo packets leaving 🧠 Key conclusion: Server receives traffic but does not forward it.\nPhase 5 - Identify root cause Check on server:\nsysctl net.ipv4.ip_forward Root Cause:\nIP forwarding disabled Server is NOT acting as router ✅ Remediation Step 1 - Enable forwarding sudo sysctl -w net.ipv4.ip_forward=1 Step 2 - Add NAT sudo iptables -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE Step 3 - Testing On client:\nping 8.8.8.8 🧠 FINAL ANALYSIS | Layer | Status | | L2 (MAC,ARP) | ✅ working | | L3 (routing) | ❌ broken | | Fix | Enable forwarding |\n","permalink":"https://my-it-blog.netlify.app/posts/tcp-ip-forwarding-failure/","summary":"\u003ch1 id=\"-inter-interface-packet-forwarding-failure-investigation\"\u003e🧪 Inter-Interface Packet Forwarding Failure Investigation\u003c/h1\u003e\n\u003ch2 id=\"-objective\"\u003e📌 Objective\u003c/h2\u003e\n\u003cp\u003eDiagnose why a client cannot reach the internet\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-environment\"\u003e⚙️ Environment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVirtualization: VirtualBox\u003c/li\u003e\n\u003cli\u003eOS: ( 1 DHCP Server VM + 1 Client VM)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"-lab-network-topology\"\u003e🛠️ Lab Network Topology\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eServer (DHCP)\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIP: 192.168.10.10\u003c/li\u003e\n\u003cli\u003eInterfaces:\n\u003cul\u003e\n\u003cli\u003eenp0s8 -\u0026gt; LAN\u003c/li\u003e\n\u003cli\u003eenp0s3 -\u0026gt; NAT\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eClient VM\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIP: 192.168.10.100\u003c/li\u003e\n\u003cli\u003eInterface: enp0s8\u003c/li\u003e\n\u003cli\u003eGateway: 192.168.10.10\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"-incident-statement\"\u003e🚨 Incident Statement\u003c/h2\u003e\n\u003cp\u003eClient cannot access the internet\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-phase-1--verify-the-problem\"\u003e🔍 PHASE 1 — Verify the Problem\u003c/h2\u003e\n\u003cp\u003eRun on Client VM:\u003c/p\u003e","title":"Inter-Interface Packet Forwarding Failure Investigation"},{"content":"🧪 Process Management \u0026amp; Resource Control Lab 📌 Objective Simulate and troubleshoot a real-world system slowdown caused by CPU saturation and memory exhaustion.\n⚙️ Environment Virtualization: VirtualBox OS: Ubuntu Server 🛠️ Lab Setup Step 1 - Create CPU Load Script nano cpu_hog.sh chmod +x cpu_hog.sh Step 2 - Create Memory Load Script (Python) nano mem_hog.py chmod +x mem_hog.py 🚨 Incident Simulation Step 1 - Check the System Load Baseline uptime Step 2 - Run the scripts ./cpu_hog.sh \u0026amp; python3 mem_hog.py \u0026amp; 🔍 Investigation Step 1 - Check System Load ``bash uptime\n![Anomaly](uptime_anomaly.png) --- ### Step 2 - Monitor Processes ```bash htop Step 3 - Identify Top Resource Consumers ps aux --sort=-%cpu | head ps aux --sort=-%mem | head 🧠 Analysis System State CPU: Fully saturated by multiple cpu_hog.sh processes Memory: Exhausted due to mem_hog.py Swap: Fully utilized (~2GB) Kernel Action: OOM killer terminates mem_hog.py Key Observations* CPU saturation causes system lag Memory exhaustion triggers OOM killer High swap usage leads to severe performance degradation Multiple processes contribute to system overload ✅ Remediation Step 1 - Kill CPU-Intensive Processes kill cpu-hog.sh Step 2 - Verify Memory Status free -h Step 3 - Confirm Recovery uptime htop 🧪 Experiment (Level 1) - Make the problem less obvious 🛠️ Setup (Disguise the process) mv cpu_hog.sh systemd-helper ./systemd-helper \u0026amp; 🔎 Investigation Step 1 - Check System Load uptime Step 2 - Monitor Processes htop Conclusion: The system slowdown is caused by a CPU-bound workload, not memory pressure.\nStep 3 - What is this process ps aux | grep systemd-helper which systemd-helper ls -l /proc/\u0026lt;PID\u0026gt;/exe Conclusion: The process is a shell script executed via bash, not a compiled system binary. The process is not installed system-wide and is not part of standard system tools. The process is running through the bash interpreter, confirming it is a script, not a native executable.\nStep 4 - Who is running it ps -o user,pid,cmd -p \u0026lt;PID\u0026gt; Conclusion: The script is executed from a local directory (./), which is atypical for legitimate system services.\nStep 5 - What is the command exactly ps -fp \u0026lt;PID\u0026gt; Step 6 - Check parent process pstree -p \u0026lt;PID\u0026gt; Conclusion: The process is a child of a bash shell, meaning it was launched from an interactive or script-based shell session, not by a system manager like systemd\n🧠 Final Summary CPU is fully saturated → confirms system slowdown source Process is a bash script, not a system binary Not found in system PATH → not an installed service Executed from local directory → suspicious / non-standard Parent service (bash) → not part of system infrastructure 🧾 Final Diagnosis The system slowdown is caused by a manually executed shell script (systemd-helper) consuming excessive CPU. The process is not a legitimate system service and operates outside standard system management.\n⚖️ Final Decision The process is safe to terminate, as it is:\nNon-critical User-executed Resource-intensive Directly responsible for system degradation 🧪 Experiment (Level 2) - Persistent Process 🛠️ Setup (Persistant process) nano restart_cpu.sh ./restart_cpu.sh \u0026amp; 🔎 Investigation Step 1 - Check System Load uptime Step 2 - Monitor Processes htop Conclusion: The system slowdown is caused by a CPU-bound workload.\nStep 3 - Identify top process ps aux --sort=-%cpu | head Step 4 - Inspect process details ps -fp \u0026lt;PID\u0026gt; Step 5 - Verify process legitimacy ls -l /proc/\u0026lt;PID\u0026gt;/exe Conclusion: The process is a shell script executed via bash, not a compiled system binary. The process is not installed system-wide and is not part of standard system tools. The process is running through the bash interpreter, confirming it is a script, not a native executable.\nStep 6 - Analyze process hierarchy pstree -p Step 7 - Test process behavior kill \u0026lt;child_PID\u0026gt; Conclusion: The process (./systemd-helper) is being respawned (persistent)\nStep 8 - Identify root cause ps -fp \u0026lt;parent_PID\u0026gt; Conclusion: The script (restart_cpu.sh) is responsible for restarting child. The parent process (./restart_cpu.sh) is the true source of persistence\n✅ Remediation Step 1 - Kill parent process kill \u0026lt;parent PID\u0026gt; Expected outcome:\nChild process stops CPU usage drops 🧪 Experiment (Level 3) - Misleading Signal: Disk I/O Noise 🛠️ Setup (Misleading signal) nano disk_worker chmod +x disk_worker Run:\n./disk_worker \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 \u0026amp; ./restart_cpu.sh \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 \u0026amp; 🔎 Investigation Step 1 - Check System Load uptime Observation Load average is elevated\nConclusion: System is under load and requires investigation\nStep 2 - Monitor Processes htop Observation\n./systemd-helper ≈ 100% CPU dd ≈ ~0.8% CPU Memory usage stable (~161MB/2GB) Conclusion: CPU saturation is dominated by a single process (systemd-helper). Disk-related processes (dd) exist but contribute minimal CPU usage. Initial-signal: CPU-bound issue\nStep 3 - Cross-check top CPU consumers ps aux --sort=-%cpu | head Observation\n./systemd-helper ≈ 88% CPU dd ≈ ~20% CPU Conclusion: CPU usage confirms:\nsystemd-helper is a consistent high consumer dd contributes CPU intermittently (burst behavior) Step 4 - Check disk activity iotop-c Observation\nMultiple dd processes appear I/O usage visibly active (graph column moving) Conclusion: Disk I/O is actively being generated, primarily by dd. However, presence of activity ≠ proof of bottleneck.\nStep 5 - Detect process behavior pattern pgrep -a dd Observation\nMultiple PIDs for dd Processes appear and disappear rapidly Conclusion: dd is a short-lived worker process, likely spawned in a loop. It\u0026rsquo;s not a stable root process -\u0026gt; must trace parent\nStep 6: Trace process origin Method A - Real time capture\nwatch -n 0.5 \u0026#34;ps -o pid,ppid,cmd -C dd\u0026#34; Method B - Process tree\npstree -p | grep dd Method C - Manual tracing\nps -fp \u0026lt;PPID\u0026gt; Observation\ndd processes originate from a parent script (disk-worker) Conclusion: dd is a child process, not root cause. A controller script is responsible for generating disk load.\n🧠 Interim Analysis Signals observed:\nCPU -\u0026gt; heavily saturated by systemd-helper Disk -\u0026gt; active due to dd Memory -\u0026gt; stable Interpretation: CPU load is continuous and dominant Disk activity is real but secondary/bursty\n🎯 Hypothesis H1 - CPU is the primary bottleneck\nSystem slowdown is caused by systemd-helper\nH2 - Disk I/O is the primary bottleneck\nSystem slowdown is caused by dd activity\nTest Disk Hypothesis (H2) kill \u0026lt;disk_worker PID\u0026gt; Observation\ndd processes disappear Disk activity drops systemd-helper still consuming ~ 100% CPU System remains slow Conclusion: Disk I/O is not the primary cause, it\u0026rsquo;s a secondary signal (noise)\nTest CPU Hypothesis (H1) pstree -p | grep systemd-helper kill \u0026lt;restart_cpu.sh PID\u0026gt; Observation\nsystemd-helper disappears CPU usage drops significantly System responsiveness improves immediately Conclusion: CPU saturation is the PRIMARY cause. systemd-helper is the root problem.\n🧠 Final Diagnosis Primary cause -\u0026gt; CPU saturation (systemd-helper) Secondary noise -\u0026gt; Disk I/O (dd via disk-worker) Debugging Workflow Detect system stress (uptime) Identify dominant resource (htop) Cross-check processes (ps) Identify process behavior (stable vs bursty) Trace parent processes (pstree / watch) Form hypothesis Test by removing one factor at a time Observe system response Confirm root cause 🧪 Experiment (Level 4) - Delayed Failure 🛠️ Setup (Delayed Failure) Create delayed CPU worker nano analytics_worker.py chmod +x analytics_worker.py Create delayed launcher nano delayed_start.sh chmod +x delayed_start.sh ./delayed_start.sh \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 \u0026amp; 🧠 Phase 1 — Initial State htop ps aux --sort=-%cpu | head Observation\nSystem is responsive CPU normal No obvious suspicious processes Conclusion:\nNo immediate issue detected System appears healthy ⏱️ Phase 2 — Degradation State htop ps aux --sort=-%cpu | head Observation\nanalytics_worker.py now consuming ~100% CPU Conclusion:\nIssue is time-triggered, not constant Requires correlation with recent activity 🔎 Investigation Step 1 - Identify new processes ps -eo pid,lstart,cmd --sort=start_time | tail Observation\nanalytics_worker.py started recently Conclusion: Newly started process correlates with system degradation\nStep 2 - Trace origin ps -fp \u0026lt;PID\u0026gt; pstree -p Observation\nParent process (delayed_start.sh) Conclusion: Root cause is delayed execution script, not just the worker\n✅ Remediation Kill either child or parent process\nkill \u0026lt;analytics_worker PID\u0026gt; kill \u0026lt;delayed_start.sh PID\u0026gt; 🧪 Experiment (Level 5) - Resource Prioritization 📌 Objective To understand how Linux CPU scheduling priority affects process behavior under load.\n⚙️ Setup Step 1 - Start normal priority CPU process (baseline) ./systemd-helper \u0026amp; Default priority: Normal CPU scheduling priority (0)\nStep 2 - Start low-priority CPU process\nnice -n 15 ./systemd-helper \u0026amp; Meaning:\nnice 15 = lower priority than default scheduler deprioritizes this process under load 🔍 Investigation Step 1 - Observe CPU behavior htop Observation\nProcess (NI = 0) -\u0026gt; ~100% CPU Process (NI = 15) -\u0026gt; ~5% CPU Conclusion: Under CPU saturation, the scheduler allocates significantly more CPU time to the process with lower nice value (higher scheduling priority).\nStep 2 - Inspect process priority ps -o pid,ni,pri,cmd -C systemd-helper Observation\nNI = 0 -\u0026gt; PRI ≈ 19 NI = 15 -\u0026gt; PRI ≈ 4 Conclusion: ps PRI represents the kernel\u0026rsquo;s internal scheduling priority, which is dynamically derived from the niceness value. It is not directly comparable to htop PR, which uses a simplified user-level mapping (PR ≈ 20 + NI)\nStep 3 - Apply system stress Start additional load:\n./systemd-helper \u0026amp; Observation\nwith increased load, CPU competition becomes more visible NI = 0 processes consistently dominate CPU usage NI = 15 process receives significantly fewer CPU time slices Concluion: Under high system contention, the scheduler enforces priority dofferences more aggressively, making niceness effects clearly observable.\nStep 4 - Validate CPU distribution ps -eo pid,ni,pri,pcpu,cmd | grep systemd-helper Observation\nNI = 0 processes -\u0026gt; higher %CPU NI = 15 process -\u0026gt; significantly lower %CPU Conclusion: CPU usage distribution confirms scheduler bias: lower nice values receive more CPU time under load, and this difference becomes measurable over time.\n🧠 Final Insight htop shows real-time CPU distribution ps PRI shows kernel scheduling priority nice only influences CPU scheduling weight, not execution capability Differences become visible only under CPU contention ","permalink":"https://my-it-blog.netlify.app/posts/process-management--resource-control/","summary":"\u003ch1 id=\"-process-management--resource-control-lab\"\u003e🧪 Process Management \u0026amp; Resource Control Lab\u003c/h1\u003e\n\u003ch2 id=\"-objective\"\u003e📌 Objective\u003c/h2\u003e\n\u003cp\u003eSimulate and troubleshoot a real-world system slowdown caused by CPU saturation and memory exhaustion.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-environment\"\u003e⚙️ Environment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVirtualization: VirtualBox\u003c/li\u003e\n\u003cli\u003eOS: Ubuntu Server\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"-lab-setup\"\u003e🛠️ Lab Setup\u003c/h2\u003e\n\u003ch3 id=\"step-1---create-cpu-load-script\"\u003eStep 1 - Create CPU Load Script\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enano cpu_hog.sh\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003echmod +x cpu_hog.sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"cpu_script\" loading=\"lazy\" src=\"/posts/process-management--resource-control/cpu_heavy_script.png\"\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch3 id=\"step-2---create-memory-load-script-python\"\u003eStep 2 - Create Memory Load Script (Python)\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enano mem_hog.py\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003echmod +x mem_hog.py\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"py_script\" loading=\"lazy\" src=\"/posts/process-management--resource-control/mem_heavy_py_script.png\"\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-incident-simulation\"\u003e🚨 Incident Simulation\u003c/h2\u003e\n\u003ch3 id=\"step-1---check-the-system-load-baseline\"\u003eStep 1 - Check the System Load Baseline\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euptime\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"Baseline\" loading=\"lazy\" src=\"/posts/process-management--resource-control/uptime_baseline.png\"\u003e\u003c/p\u003e","title":"Process Management \u0026 Resource Control Lab"},{"content":"🧪 DHCP Lab 📌 Objective Understand how DHCP works in real network environment and how to debug common failure scenarios using a structured top-to-bottom approach.\n⚙️ Environment Virtualization: VirtualBox OS: Ubuntu Server (1 DHCP Server VM \u0026amp; 2 Client VMs) Network mode: Internal Network + NAT (enp0s3 ignored for DHCP lab) 🛠️ Network Setup Interfaces DHCP Server\nenp0s8 -\u0026gt; 192.168.10.10/24 (Lab network) enp0s3 -\u0026gt; NAT Clients\nenp0s8 -\u0026gt; DHCP assigned IPs enp0s3 -\u0026gt; NAT (not used) ⚙️ Network Configuration (Netplan) Both server and clients are configured using Netplan, which defines interface behavior before DHCP starts.\n🖥️ Client VM Netplan\nsudo nano /etc/netplan/01-netcfg.yaml Meaning:\nenp0s3 -\u0026gt; NAT IP automatically assigned enp0s8 -\u0026gt; requests IP from DHCP server 🖥️ DHCP Server VM Netplan\nsudo nano /etc/netplan/01-netcfg.yaml Meaning:\nenp0s8 is STATIC (required for DHCP sever stability) enp0s3 remains NAT DHCP server must always have fixed IP in lab network ⚙️ DHCP Server Configuration sudo nano /etc/dhcp/dhcpd.conf ⚙️ DHCP Server Interface Binding Before DHCP can operate, it must bind to the correct interface:\nsudo nano /etc/default/isc-dhcp-server ✅ Validation Flow Step 1 - Start DHCP Service sudo systemctl start isc-dhcp-server Check status:\nsudo systemctl status isc-dhcp-server Step 2 - Request IP sudo dhclient -v enp0s8 Verify IP assignment:\nip a show enp0s8 Step 3 - Connectivity test ping 192.168.10.100 🧪 Challenge 1 - DHCP Service Fails to Start (Wrong Interface Binding) Edit config to create a subnet mismatch:\nsudo nano /etc/default/isc-dhcp-server INTERFACEv4=\u0026#34;enp0s3\u0026#34; Expected outcome:\nDHCP service fails to start Client stuck in DHCPDISCOVER No IP assignment 🔥 Debugging Step 1 - Check service: systemctl status isc-dhcp-server Step 2 - Check logs: sudo journalctl -u isc-dhcp-server Error: No subnet declaration for enp0s3 (10.0.2.15)\n🧠 Root Cause DHCP is bound to enp0s3 (NAT) No matching subnet config exists for that interface Service cannot start ✅ Remediation Bind DHCP to correct interface:\nsudo nano /etc/default/isc-dhcp-server INTERFACEv4=\u0026#34;enp0s8\u0026#34; Restart the DHCP service:\nsudo systemctl restart isc-dhcp-server 🧪 Challenge 2 - Pool Exhaustion Edit dhcpd.conf to reduce the pool to a single IP:\nsudo nano /etc/dhcp/dhcpd.conf subnet 192.168.10.0 netmask 255.255.255.0 { range 192.168.10.100 192.168.10.100; } Expected outcome:\nClient A -\u0026gt; gets IP Client B -\u0026gt; stuck in DHCPDICOVER 🔥 Debugging Step 1 - Check service systemctl status isc-dhcp-server Interpretation\nDHCP Service is running ✅ DHCP is receiving requests ✅ DHCP is refusing allocation ❗ Step 2 - Check logs sudo journlctl -u isc-dhcp-server Result:\nrepeated no free leases Step 3 - Check lease file\ncat /var/lib/dhcp/dhcpd.leases Result:\npool fully assigned single active lease 🧠 Root Cause Pool size = 1 Lease already assigned No available IPs DHCP is functioning correctly, but the IP pool is exhausted.\n✅ Remediation Expand pool:\nsudo nano /etc/dhcp/dhcpd.conf range 192.168.10.100 192.168.10.200; Restart the service:\nsudo systemctl restart isc-dhcp-server 🧠 Key lessons Interface binding is critical DHCP must match subnet to interface Logs reveal root cause quickly 🔥 Debugging hierarchy Check service Check logs Check traffic Check leases Validate client ","permalink":"https://my-it-blog.netlify.app/posts/dhcp-server/","summary":"\u003ch1 id=\"-dhcp-lab\"\u003e🧪 DHCP Lab\u003c/h1\u003e\n\u003ch2 id=\"-objective\"\u003e📌 Objective\u003c/h2\u003e\n\u003cp\u003eUnderstand how DHCP works in real network environment and how to debug common failure scenarios using a structured top-to-bottom approach.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-environment\"\u003e⚙️ Environment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVirtualization: VirtualBox\u003c/li\u003e\n\u003cli\u003eOS: Ubuntu Server (1 DHCP Server VM \u0026amp; 2 Client VMs)\u003c/li\u003e\n\u003cli\u003eNetwork mode: Internal Network + NAT (enp0s3 ignored for DHCP lab)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"-network-setup\"\u003e🛠️ Network Setup\u003c/h2\u003e\n\u003ch3 id=\"interfaces\"\u003eInterfaces\u003c/h3\u003e\n\u003cp\u003eDHCP Server\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eenp0s8 -\u0026gt; 192.168.10.10/24 (Lab network)\u003c/li\u003e\n\u003cli\u003eenp0s3 -\u0026gt; NAT\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eClients\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eenp0s8 -\u0026gt; DHCP assigned IPs\u003c/li\u003e\n\u003cli\u003eenp0s3 -\u0026gt; NAT (not used)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch3 id=\"-network-configuration-netplan\"\u003e⚙️ Network Configuration (Netplan)\u003c/h3\u003e\n\u003cp\u003eBoth server and clients are configured using Netplan, which defines interface behavior before DHCP starts.\u003c/p\u003e","title":"DHCP Lab: Setup, Failure Scenarios \u0026 Debugging Workflow"},{"content":"🧪 Basic Network Setup \u0026amp; Connectivity Lab 📌 Objective Understand how IP addressing, subnetting, and basic connectivity work in a controlled virtual environment.\n⚙️ Environment Virtualization: VirtualBox OS: Ubuntu Server (2 VMs) Network mode: Internal Network + NAT VMs\nVM IP Address Role VM1 192.168.10.10/24 Client VM2 192.168.10.20/24 Server 🛠️ Setup Step 1 - Create Virtual Machines Create two Linux virtual machines:\nserver_01 server_02 Recommended specs:\n1 CPU 1-2 GB RAM 10+ GB disk Step 2 - Configure Network Both VMs must use the same Internal Network This ensures both machines are on the same isolated Layer 2 network.\nStep 3 - Assign Static IPs server_01 and server_02 configuration\nEdit netplan:\nsudo nano /etc/netplan/01-netcfg.yaml sudo netplan apply Step 4 - Verify configuration Check ip addresses:\nip a Expectet output:\nserver_01 -\u0026gt; 192.168.10.10 server_02 -\u0026gt; 192.168.10.20 Step 5 - Connectivity Test From server_01:\nping 192.168.10.20 From server_02:\nping 192.168.10.10 Expected result:\nSuccessful ICMP replies Direct communication (same subnet) Step 6 - Traceroute Test Install traceroute:\nsudo apt install traceroute Traceroute test:\ntraceroute 192.168.10.20 Expected result:\nSingle hop (direct connection) No routes involved 🧪 Experiment - Break the Network (Subnet Mismatch) Change server_02 IP\naddresses: - 192.168.20.20/24 sudo netplan apply 🧠 Debugging Confirm local network configuration On server_01:\nip a Expected result:\nCorrect IP assigned (192.168.10.10/24) Correct subnet mask (/24) Verify routing table ip route Key observation:\nOnly local subnet route exists No route to 192.168.20.0/24 Check target host reachability assumption Verify server_02 configuration:\nip a Key observation:\nTarget IP is valid (192.168.20.20/24) server_02 belongs to a different subnet Analyze packet decision process When server_01 send traffic:\nping 192.168.20.20 Linux checks routing table:\nIs 192.168.20.20 in 192.168.10.0/24 ? -\u0026gt; ❌ No Use default gateway Validate gateway capability Check assumption:\nDefault gateway is NAT (VirtualBox) It has no route to internal lab networks Result: ❌ Gateway cannot reach 192.168.20.0/24\nConfirm absence of router between the subnets Check environment design:\nOnly two VMs exist No routing device configured No IP forwarding enabled Conclusion: 👉 No Layer 3 device connects both networks\n🚨 Root Cause\nThe issue is:\n❌ Subnet mismatch with no routing infrastructure\nSpecifically:\nserver_01: 192.168.10.0/24 server_02: 192.168.20.0/24 No router exists between them 🔧 Resolution Restore same subnet on server_02:\naddresses: - 192.168.10.20/24 sudo netplan apply 🧪 Validation from server_01:\nping 192.168.10.20 🧠 Key Takeaways Devices must be in the same subnet for direct communication Routing is required between different networks Linux always checks routing table before sending packets Default gateway is only used when no local route exists 🧭 Mental Model When troubleshooting connectivity:\nIs IP correct? Is subnet correct? Is destination in routing table? Is a router required? Does the router actually exists? ","permalink":"https://my-it-blog.netlify.app/posts/basic-network-setup-connectivity/","summary":"\u003ch1 id=\"-basic-network-setup--connectivity-lab\"\u003e🧪 Basic Network Setup \u0026amp; Connectivity Lab\u003c/h1\u003e\n\u003ch2 id=\"-objective\"\u003e📌 Objective\u003c/h2\u003e\n\u003cp\u003eUnderstand how IP addressing, subnetting, and basic connectivity work in a controlled virtual environment.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-environment\"\u003e⚙️ Environment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVirtualization: VirtualBox\u003c/li\u003e\n\u003cli\u003eOS: Ubuntu Server (2 VMs)\u003c/li\u003e\n\u003cli\u003eNetwork mode: Internal Network + NAT\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eVMs\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003eVM\u003c/th\u003e\n          \u003cth\u003eIP Address\u003c/th\u003e\n          \u003cth\u003eRole\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eVM1\u003c/td\u003e\n          \u003ctd\u003e192.168.10.10/24\u003c/td\u003e\n          \u003ctd\u003eClient\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eVM2\u003c/td\u003e\n          \u003ctd\u003e192.168.10.20/24\u003c/td\u003e\n          \u003ctd\u003eServer\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003chr\u003e\n\u003ch2 id=\"-setup\"\u003e🛠️ Setup\u003c/h2\u003e\n\u003ch3 id=\"step-1---create-virtual-machines\"\u003eStep 1 - Create Virtual Machines\u003c/h3\u003e\n\u003cp\u003eCreate two Linux virtual machines:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eserver_01\u003c/li\u003e\n\u003cli\u003eserver_02\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eRecommended specs:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e1 CPU\u003c/li\u003e\n\u003cli\u003e1-2 GB RAM\u003c/li\u003e\n\u003cli\u003e10+ GB disk\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch3 id=\"step-2---configure-network\"\u003eStep 2 - Configure Network\u003c/h3\u003e\n\u003cp\u003eBoth VMs must use the same \u003cstrong\u003eInternal Network\u003c/strong\u003e\nThis ensures both machines are on the same isolated Layer 2 network.\u003c/p\u003e","title":"Basic Network Setup \u0026 Connectivity"},{"content":"🧪 Linux Networking and Service Exposure Lab 📌 Objective This lab simulates real-world Linux networking issues and teaches how to troubleshoot:\nService availability Port listening Firewall behavior (UFW) Binding (\u0026rsquo;localhost\u0026rsquo; vs external access) Network-layer debugging ⚙️ Environment OS: Ubuntu (VM + Bridged Adapter) Service: Nginx Tools: ss, curl, ufw, systemctl Host machine for external testing (Powershell) 🟢 Stage 1 Verify service:\nsystemctl status nginx Expected outcome: Active (running)\nCheck listening ports:\nss - tuln | grep :80 Expected outcome: 0.0.0.0:80\nTest locally:\ncurl 192.160.0.199 Test from host:\nTest-NetConnection 192.168.0.199 -Port 80 🔴 Stage 2 - Break the System 🧪 Challenge 1 - Firewall Block sudo ufw enable sudo ufw deny 80 Expected Outcome:\nLocal curl works External connection fails 🔥 Debugging Confirm service is running: systemctl status nginx Confirm port is listening: ss -tuln | grep :80 Expected Outcome:\n0.0.0.0:80\nTest local access: curl http://localhost Check firewall state: sudo ufw status verbose 🧠 Diagnosis Service run locally but not externally -\u0026gt; firewall is blocking TCP traffic\n🛠 Fix sudo ufw allow 80/tcp or\nsudo ufw disable ✅ Verification From host:\n🧠 Key lesson PING working does not mean service is reachable Firewall blocks TCP, not ICMP in many cases 🧪 Challenge 2 - Bind to localhost only Edit conf:\nsudo nano /etc/nginx/sites-available/default Change:\nlisten 127.0.0.1:80; listen [::1]:80; Restart:\nsudo systemctl restart nginx Expected outcome:\ncurl localhost works ✔ curl IP fails ❌ Host access fails ❌ 🔥 Debugging Check service: systemctl status nginx Check listening interface: ss -tuln | grep :80 Expected Outcome:\n127.0.0.1:80\nTest localhost explicitly: curl http://localhost Test network IP address: curl 192.168.0.199 Confirm config source: nginx -T | grep listen 🧠 Diagnosis Service is restricted to loopback interface -\u0026gt; not exposed to network\n🛠 Fix Edit config:\nsudo nano /etc/nginx/sites-available/default Restart:\nsudo systemctl restart nginx ✅ Verification ss -tuln | grep :80 curl http://192.168.0.199 🧠 Key lesson Binding defines WHO can connect, not whether service runs\n🧪 Challenge 3 - Wrong Port Edit config:\nlisten 8080; listen [::]:8080; Restart:\nsudo systemctl restart nginx Expected outcome:\nPort 80 fails ❌ Port 8080 works ✔ 🔥 Debugging Check service status: systemctl status nginx Check listening ports: ss -tuln | grep LISTEN 👉 Nginx is NOT listening on port 80\nTest discovered port locally: Verify from host: Confirm config: nginx -T | grep Expected Outcome:\nlisten 8080;\n🧠 Diagnosis Service is running on the wrong port -\u0026gt; client is connecting to the wrong port\n🛠 Fix Edit config:\nsudo nano /etc/nginx/sites-available/default listen 80 default_server; listen [::]:80 default_server; Restart:\nsudo systemtctl restart nginx ✅ Verification ss -tuln | grep :80 Test-NetConnection 192.168.0.199 -Port 80 🧠 Key lesson Service may be fully healthy but unreachable due to port mismatch\n🔥 Debugging hierarchy Service (running?) Port (listening?) Binding (where?) Firewall (blocked?) Network (reachable?) ","permalink":"https://my-it-blog.netlify.app/posts/network--service-connectivity/","summary":"\u003ch1 id=\"-linux-networking-and-service-exposure-lab\"\u003e🧪 Linux Networking and Service Exposure Lab\u003c/h1\u003e\n\u003ch2 id=\"-objective\"\u003e📌 Objective\u003c/h2\u003e\n\u003cp\u003eThis lab simulates real-world Linux networking issues and teaches how to troubleshoot:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eService availability\u003c/li\u003e\n\u003cli\u003ePort listening\u003c/li\u003e\n\u003cli\u003eFirewall behavior (UFW)\u003c/li\u003e\n\u003cli\u003eBinding (\u0026rsquo;localhost\u0026rsquo; vs external access)\u003c/li\u003e\n\u003cli\u003eNetwork-layer debugging\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"-environment\"\u003e⚙️ Environment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eOS: Ubuntu (VM + Bridged Adapter)\u003c/li\u003e\n\u003cli\u003eService: Nginx\u003c/li\u003e\n\u003cli\u003eTools: ss, curl, ufw, systemctl\u003c/li\u003e\n\u003cli\u003eHost machine for external testing (Powershell)\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"-stage-1\"\u003e🟢 Stage 1\u003c/h2\u003e\n\u003cp\u003eVerify service:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esystemctl status nginx\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eExpected outcome:\nActive (running)\u003c/p\u003e\n\u003cp\u003eCheck listening ports:\u003c/p\u003e","title":"Linux Networking"},{"content":"🧪 Log Analysis \u0026amp; System Debugging Lab 📌 Objective Read system logs like real incidents Identify root causes Debug common system failures ⚙️ Environment OS: Ubuntu Tools: journalctl, df, du, dmesg 🚨 Scenario 1: Service Crash Investigation Step 1 - Break the service sudo nano /etc/nginx/nginx.conf Add invalid line:\ninvalid_directive; Restart:\nsudo systemctl restart nginx Step 2 - Investigate Check status:\nsystemctl status nginx Check logs:\nsudo journalctl -u nginx -n 50 --no-pager Switch to application-level debugging:\nsudo nginx -t Step 3 - Fix conf Remove bad line \u0026ldquo;invalid_directive\u0026rdquo;\nStep 4 - Verify sudo nginx -t sudo systemctl restart nginx 🚨 Scenario 2: Disk Full Incident Step 1 - Fill disk sudo fallocate -l 16G /bigfile Step 2 - Trigger failiure echo \u0026#34;hello\u0026#34; \u0026gt; file.txt 🔍 Expected Result: No space left on device\nStep 3 - Investigate df -h Check system messages:\ndmesg | grep -i space Check logs (may be unreliable):\nsudo systemctl -xe Find what filled the disk:\ndu -sh /* 2\u0026gt;/dev/null Step 4 - Fix the issue: sudo rm /bigfile df -h Step 5 - Verify recovery: echo \u0026#34;test\u0026#34; \u0026gt; file.txt 🧠 Key Takeaways Disk issues often look like unrelated failures Logs may fail or be incomplete Always check disk first Must verify fixes, not assume ","permalink":"https://my-it-blog.netlify.app/posts/log-analysis--system-debug/","summary":"\u003ch1 id=\"-log-analysis--system-debugging-lab\"\u003e🧪 Log Analysis \u0026amp; System Debugging Lab\u003c/h1\u003e\n\u003ch2 id=\"-objective\"\u003e📌 Objective\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eRead system logs like real incidents\u003c/li\u003e\n\u003cli\u003eIdentify root causes\u003c/li\u003e\n\u003cli\u003eDebug common system failures\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"-environment\"\u003e⚙️ Environment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eOS: Ubuntu\u003c/li\u003e\n\u003cli\u003eTools: journalctl, df, du, dmesg\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"-scenario-1-service-crash-investigation\"\u003e🚨 Scenario 1: Service Crash Investigation\u003c/h2\u003e\n\u003ch3 id=\"step-1---break-the-service\"\u003eStep 1 - Break the service\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nano /etc/nginx/nginx.conf\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eAdd invalid line:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003einvalid_directive;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eRestart:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl restart nginx\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"step-2---investigate\"\u003eStep 2 - Investigate\u003c/h3\u003e\n\u003cp\u003eCheck status:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esystemctl status nginx\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"Nginx\" loading=\"lazy\" src=\"/posts/log-analysis--system-debug/nginx.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Failed\" loading=\"lazy\" src=\"/posts/log-analysis--system-debug/failed_nginx.png\"\u003e\u003c/p\u003e\n\u003cp\u003eCheck logs:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo journalctl -u nginx -n \u003cspan style=\"color:#ae81ff\"\u003e50\u003c/span\u003e --no-pager\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"Journal\" loading=\"lazy\" src=\"/posts/log-analysis--system-debug/journalctl.png\"\u003e\u003c/p\u003e","title":"Log Analysis \u0026 System Debugging"},{"content":"🧪 Linux Permission and Access Control Lab 📌 Objective To test how Linux file permissions and access control mechanisms work in a multi-user environment.\n⚙️ Environment OS: Ubuntu Tools: chmod, chown, ls, groups, sudo Users: alice, bob, admin Groups: devs, managers 🛠️ Setup 1. Create Users sudo adduser alice sudo adduser bob sudo adduser admin 2. Create Groups sudo groupadd devs sudo groupadd managers Assign users:\nsudo usermod -aG devs alice sudo usermod -aG managers bob sudo usermod -aG devs admin sudo usermod -aG managers admin 3. Create Shared Directory sudo mkdir -p /project/data sudo chown admin:devs /project/data sudo chmod 2770 /project/data P.S (setgid - 2) ensures all new files inherit the devs group\n4. File Creation as admin sudo -u admin echo \u0026#34;Sensitive data\u0026#34; \u0026gt; /project/data/report.txt Set permissions and ownership:\nsudo chmod 640 /project/data/report.txt 🚨 Scenario: Permission Denied Problem:\nUser bob cannot access /project/data/report.txt\n🔍 Debugging Steps Check file permissions ls -ld /project/data/report.txt Check directory permissions ls -ld /project/data Check user group membership groups bob 🛠 - Fix (Least Privilege) Add bob to devs\nsudo usermod -aG devs bob Sticky Bit (+t) chmod +t /project/data Prevents users from deleting files they do not own SetGID (g+s) chmod g+s /project/data Ensures consistent group ownership for new files 🧪 Challenge 1 Configure /project/data so:\nonly admin can delete files developers can modify files ls -ld /project/data ls -ld /project/data/alice.txt As the directory was already configured to satisfy the requirements — ownership set to admin:devs with permissions rwxrws\u0026ndash;T (SetGID + sticky bit). When Alice (a devs member) created a file inside the directory, it was correctly assigned ownership alice:devs with permissions rw-rw-r\u0026ndash;, confirming that SetGID inheritance was working as expected. However, when Bob (also a devs member) attempted to edit the file\u0026rsquo;s content, he received Permission Denied despite having group write access.\nRoot Cause After investigation, the issue was traced to a kernel-level security feature introduced in newer Linux versions. Ubuntu 24.04.3 ships with the following sysctl setting enabled by default: fs.protected_regular = 2\nThis setting restricts write access to files located in sticky bit directories — even for users who have the appropriate group write permissions. When set to 2, the kernel blocks any process from writing to a file it does not own inside a sticky+SetGID directory, regardless of what the Unix permission bits or ACLs say.\n🧪 Challenge 2 Create a file where:\nalice can read bob cannot group has no access touch file.txt chmod 400 file.txt 🧪 Challenge 3 Let\u0026rsquo;s break access intentionally:\nchmod 600 /project/data/admin.txt and let\u0026rsquo;s debug why access fails for other users.\nI checked the file with ls -l /project/data/report.txt and saw it is owned by admin with group developers. Alice is a member of the devs group, but the file permissions are set to 600, which means the group has no permissions. Therefore, even though alice is in the correct group, she cannot read the file because group access is disabled.\n🧠 Key Takeaways File vs Directory Permissions\nFile permissions control content access (read/write) Directory permissions control file operations (create/delete/access) Group Membership ≠ Access\nBeing in the correct group does not guarantee access Access depends on actual permission bits (rwx) Deletion Depends on Directory, Not File\nA user can delete a file if they have write + execute on the directory Sticky bit (+t) restricts deletion to file owner, directory owner, root SetGID Enables Collaboration\nEnsures all new files inherit the directory\u0026rsquo;s group Prevents inconsistent group ownership in shared environments Umask Affects Default Security\nControls default permissions for new files Misconfigured umask can silently break collaboration ","permalink":"https://my-it-blog.netlify.app/posts/linux-permission-access-control/","summary":"\u003ch1 id=\"-linux-permission-and-access-control-lab\"\u003e🧪 Linux Permission and Access Control Lab\u003c/h1\u003e\n\u003ch2 id=\"-objective\"\u003e📌 Objective\u003c/h2\u003e\n\u003cp\u003eTo test how Linux file permissions and access control mechanisms work in a multi-user environment.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-environment\"\u003e⚙️ Environment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eOS: Ubuntu\u003c/li\u003e\n\u003cli\u003eTools: chmod, chown, ls, groups, sudo\u003c/li\u003e\n\u003cli\u003eUsers: alice, bob, admin\u003c/li\u003e\n\u003cli\u003eGroups: devs, managers\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"-setup\"\u003e🛠️ Setup\u003c/h2\u003e\n\u003ch3 id=\"1-create-users\"\u003e1. Create Users\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo adduser alice\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo adduser bob\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo adduser admin\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003chr\u003e\n\u003ch3 id=\"2-create-groups\"\u003e2. Create Groups\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo groupadd devs\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo groupadd managers\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eAssign users:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo usermod -aG devs alice\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo usermod -aG managers bob\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo usermod -aG devs admin\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo usermod -aG managers admin\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"Add_Groups\" loading=\"lazy\" src=\"/posts/linux-permission-access-control/add_groups.png\"\u003e\u003c/p\u003e","title":"Linux Permissions \u0026 Access Control"},{"content":"🧪 Cron Job Automation Lab 📌 Objective To build a scheduled automation script, observe its behavior, and learn how to debug failures.\n⚙️ Part 1 - Script Setup Create a working directory:\nmkdir -p ~/cronlab cd ~/cronlab Create the script:\nnano backup.sh #!/bin/bash DATE=$(date +\u0026#34;%Y-%m-%d_%H-%M-%S\u0026#34;) LOG_FILE=\u0026#34;$HOME/cronlab/backup.log\u0026#34; SOURCE=\u0026#34;$HOME\u0026#34; BACKUP_DIR=\u0026#34;$HOME/cronlab/backups\u0026#34; exec \u0026gt;\u0026gt; \u0026#34;$LOG_FILE\u0026#34; 2\u0026gt;\u0026amp;1 echo \u0026#34;--- RUN $DATE ---\u0026#34; mkdir -p \u0026#34;$BACKUP_DIR\u0026#34; rsync -a --exclude=\u0026#34;cronlab\u0026#34; \\ \u0026#34;$SOURCE/\u0026#34; \u0026#34;$BACKUP_DIR/home-backup-$DATE/\u0026#34; echo \u0026#34;Backup finished\u0026#34; Make it executable:\nchmod +x backup.sh Test manually:\n./backup.sh Check log:\ncat ~/cronlab/backup.log ⏰ Part 2 - Schedule with Cron Open crontab:\ncrontab -e Add job (every two minutes):\n*/2 * * * * /home/samurai/cronlab/backup.sh Verify cron service:\nsystemctl status cron Monitor execution:\ntail -f ~/cronlab/backup.log 💣 Part 3 — Failure Testing 🔴 Test 1 - Broken Command Replace rsync with:\ncp_not_exist /fake/source /fake/dest 🔴 Test 2 — Missing Full Path Edit crontab:\n*/2 * * * * backup.sh 👉 Script will not run.\nReason: cron has no working directory context.\n🔴 Test 3 - Remove Execute Permission chmod -x ~/cronlab/backup.sh 👉 Script does not run at all.\n👉 No logs appear (script never starts).\n🔴 Test 4 - Silent Failure Remove logging line:\n# exec \u0026gt;\u0026gt; \u0026#34;$LOG_FILE\u0026#34; 2\u0026gt;\u0026amp;1 👉 Cron runs, but no visible output.\n📜 Part 4 - Logging Strategy Key Concept\nstdout - normal output stderr - errors both redirected into one log file 🧠 Key Takeaways Always use absolute paths Failures can be silent Logging must be explicit Some errors occur before the script even starts ","permalink":"https://my-it-blog.netlify.app/posts/cron-job-automation/","summary":"\u003ch1 id=\"-cron-job-automation-lab\"\u003e🧪 Cron Job Automation Lab\u003c/h1\u003e\n\u003ch2 id=\"-objective\"\u003e📌 Objective\u003c/h2\u003e\n\u003cp\u003eTo build a scheduled automation script, observe its behavior, and learn how to debug failures.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-part-1---script-setup\"\u003e⚙️ Part 1 - Script Setup\u003c/h2\u003e\n\u003cp\u003eCreate a working directory:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir -p ~/cronlab\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd ~/cronlab\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eCreate the script:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enano backup.sh\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#!/bin/bash\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDATE\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003edate +\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%Y-%m-%d_%H-%M-%S\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eLOG_FILE\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$HOME\u003cspan style=\"color:#e6db74\"\u003e/cronlab/backup.log\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSOURCE\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$HOME\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eBACKUP_DIR\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$HOME\u003cspan style=\"color:#e6db74\"\u003e/cronlab/backups\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexec \u0026gt;\u0026gt; \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$LOG_FILE\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e 2\u0026gt;\u0026amp;\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;--- RUN \u003c/span\u003e$DATE\u003cspan style=\"color:#e6db74\"\u003e ---\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir -p \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$BACKUP_DIR\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ersync -a --exclude\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;cronlab\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$SOURCE\u003cspan style=\"color:#e6db74\"\u003e/\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$BACKUP_DIR\u003cspan style=\"color:#e6db74\"\u003e/home-backup-\u003c/span\u003e$DATE\u003cspan style=\"color:#e6db74\"\u003e/\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Backup finished\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"Script\" loading=\"lazy\" src=\"/posts/cron-job-automation/script.png\"\u003e\u003c/p\u003e","title":"Cron Job Automation"},{"content":"🧪 Systemd Service Restart Behavior Lab 📌 Objective To test and understand how systemd handles automatic service restarts using the Restart=on-failure policy.\n⚙️ Environment OS: Ubuntu (systemd-based) Tools: systemctl, journalctl, bash 🛠️ Setup 1. Create a test script sudo nano /usr/local/bin/labtest.sh #!/bin/bash while true; do echo \u0026#34;lab service is alive: $(date)\u0026#34; sleep 10 done Make it executable:\nsudo chmod +x /usr/local/bin/labtest.sh 2. Create a system service sudo nano /etc/systemd/system/labtest.service [Unit] Description=Lab test service After=network.target [Service] ExecStart=/usr/local/bin/labtest.sh Restart=on-failure StandardOutput=journal [Install] WantedBy=multi-user.target Step 3 — Start the service sudo systemctl daemon-reload sudo systemctl enable labtest sudo systemctl start labtest systemctl status labtest Step 4 — Monitor Logs sudo journalctl -u labtest -f 🧪 Experiment 1 - Killing the Service (SIGTERM) sudo kill PID\u0026lt;labtest\u0026gt; Expected Result: The service should restart automatically\nActual Result: The service did not restart\n🔍 Investigation The kill command sends SIGTERM (signal 15) by default.\nSystemd treats SIGTERM as a graceful stop, meaning:\nthe process exists normally exit status = 0 (SUCCESS) Because of this, Restart=on-failure is not triggered.\n🧪 Experiment 2 - Forcing a Failure (SIGKILL) sudo kill -9 PID\u0026lt;labtest\u0026gt; Result: The service started automatically.\nExplanation:\nkill -9 sends SIGKILL the process is terminated abruptly system detects this as a failure restart is triggered 🧪 Experiment 3 - Simulating Application Failure Modify the script:\nsudo nano /usr/local/bin/labtest.sh #!/bin/bash while true; do echo \u0026#34;lab service is alive: $(date)\u0026#34; sleep 10 if [ $((RANDOM % 5)) -eq 0 ]; then echo \u0026#34;Simulated failure\u0026#34; exit 1 fi done Restart the service:\nsudo systemctl restart labtest Result: The service restarts automatically when it exits with an error.\n📊 Summary Action Signal Result Restart kill SIGTERM Clean stop No kill -9 SIGKILL Forced failure Yes exit 1 N/A Application Error Yes 🧠 Key Takeaways Restart=on-failure depends on exit status SIGTERM is treated as a normal stop SIGKILL is treated as a failure Proper testing requires simulating real failures ","permalink":"https://my-it-blog.netlify.app/posts/systemd-restart-behavior/","summary":"\u003ch1 id=\"-systemd-service-restart-behavior-lab\"\u003e🧪 Systemd Service Restart Behavior Lab\u003c/h1\u003e\n\u003ch2 id=\"-objective\"\u003e📌 Objective\u003c/h2\u003e\n\u003cp\u003eTo test and understand how \u003ccode\u003esystemd\u003c/code\u003e handles automatic service restarts using the \u003ccode\u003eRestart=on-failure\u003c/code\u003e policy.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-environment\"\u003e⚙️ Environment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eOS: Ubuntu (systemd-based)\u003c/li\u003e\n\u003cli\u003eTools: systemctl, journalctl, bash\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch2 id=\"-setup\"\u003e🛠️ Setup\u003c/h2\u003e\n\u003ch3 id=\"1-create-a-test-script\"\u003e1. Create a test script\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nano /usr/local/bin/labtest.sh\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#!/bin/bash\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e true; \u003cspan style=\"color:#66d9ef\"\u003edo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\techo \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;lab service is alive: \u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003edate\u003cspan style=\"color:#66d9ef\"\u003e)\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tsleep \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edone\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eMake it executable:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo chmod +x /usr/local/bin/labtest.sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003chr\u003e\n\u003ch3 id=\"2-create-a-system-service\"\u003e2. Create a system service\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nano /etc/systemd/system/labtest.service\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eUnit\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDescription\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eLab test service\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAfter\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003enetwork.target\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eService\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStart\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e/usr/local/bin/labtest.sh\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRestart\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eon-failure\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eStandardOutput\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ejournal\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eInstall\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWantedBy\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003emulti-user.target\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003chr\u003e\n\u003ch3 id=\"step-3--start-the-service\"\u003eStep 3 — Start the service\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl daemon-reload\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl enable labtest\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl start labtest\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esystemctl status labtest\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"Status\" loading=\"lazy\" src=\"/posts/systemd-restart-behavior/labtest-status.png\"\u003e\u003c/p\u003e","title":"Systemd Restart Behavior: Why Restart=on-failure Didn't Work"},{"content":"🚨 The Alert Time: 2:04 AM\nAlert: PagerDuty - server \u0026lsquo;web-prod-03\u0026rsquo; unreachable\nSLA: Server must be back online within 60 minutes\nAfter attaching to the console, it was immediately clear the machine had dropped into the GRUB2 shell — it never made it to the OS.\n🖥️ Environment Detail Value Server web-prod-03 Root Partition /dev/sda2 Kernel Location /boot Target SLA \u0026lt; 60 min 🔍 What Went Wrong The GRUB2 configuration file /boot/grub/grub.cfg was missing or corrupted, so the bootloader had no instructions on where to find the kernel.\nLab Note: To simulate this failure:\nmv /boot/grub/grub.cfg /boot/grub/grub.cfg.bak ⏱️ Incident Timeline Time Action 02:04 PagerDuty alert received 02:07 Attached to console 02:11 Root partition identified 02:18 Server back online 02:35 GRUB config regenerated 🛠️ Step-by-Step Recovery Step 1 — List Available Devices ls Output: (hd0) (hd0,gpt1) (hd0,gpt2)\nStep 2 — Find the Root Filesystem ls (hd0,gpt2)/boot/ Output: vmlinuz + initrd\nRoot filesystem identified: (hd0,gpt2)\nStep 3 — Load Normal Mode set root=(hd0,gpt2) set prefix=(hd0,gpt2)/boot/grub insmod normal normal If the boot menu appears, select your kernel and boot normally.\nStep 4 — Manual Boot (If Needed) insmod linux linux (hd0,gpt2)/boot/vmlinuz-6.17.0-19-generic root=/dev/sda2 ro initrd (hd0,gpt2)/boot/initrd.img-6.17.0-19-generic boot Step 5 — Make Fix Permanent On Debian/Ubuntu:\nsudo update-grub On RHEL/CentOS:\nsudo grub2-mkconfig -o /boot/grub2/grub.cfg Verify:\nls -lh /boot/grub/grub.cfg ✅ Resolution Server restored at 02:18 (14 minutes after alert).\nPermanent fix completed at 02:35, within SLA.\n📚 Lessons Learned Always verify /boot/grub/grub.cfg after kernel updates GRUB shell recovery is a critical skill Document partition layout (lsblk) before incidents ","permalink":"https://my-it-blog.netlify.app/posts/grub-recovery/","summary":"A step-by-step account of recovering a production server that dropped into the GRUB2 rescue shell at 2AM, resolved within SLA.","title":"Grub2 Boot Recovery: Restoring a Server at 2AM"},{"content":"Why I started this blog I am a beginner in IT and I want to document every problem I solve as I learn\nWhat I plan to write about Linux \u0026amp; Windows Troubleshooting Network issues Tools I discover ","permalink":"https://my-it-blog.netlify.app/posts/my-first-post/","summary":"\u003ch2 id=\"why-i-started-this-blog\"\u003eWhy I started this blog\u003c/h2\u003e\n\u003cp\u003eI am a beginner in IT and I want to document every problem I solve as I learn\u003c/p\u003e\n\u003ch2 id=\"what-i-plan-to-write-about\"\u003eWhat I plan to write about\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eLinux \u0026amp; Windows Troubleshooting\u003c/li\u003e\n\u003cli\u003eNetwork issues\u003c/li\u003e\n\u003cli\u003eTools I discover\u003c/li\u003e\n\u003c/ul\u003e","title":"How I set up my IT journal"}]