Understanding Network Security: What I Learned Building Network Tools

When I first exposed my server to the internet, I naively thought a strong password would be enough security. Within hours, my logs showed thousands of failed login attempts from IP addresses around the world. That was my wake-up call to the reality of network security. This post shares my journey from security ignorance to implementing defense-in-depth strategies that actually work.

The Shocking Reality: My First Security Logs

After setting up my first VPS, I decided to check the authentication logs out of curiosity. What I found was terrifying:

My First Look at Attack Attemptsbash
1# Checking SSH authentication logs
2  sudo tail -f /var/log/auth.log
3  
4  # What I saw:
5  Failed password for root from 185.234.219.x port 45832 ssh2
6  Failed password for root from 185.234.219.x port 45832 ssh2
7  Failed password for invalid user admin from 103.145.23.x port 53281 ssh2
8  Failed password for invalid user test from 45.132.194.x port 38745 ssh2
9  Failed password for invalid user ubuntu from 167.248.133.x port 42365 ssh2
10  Failed password for invalid user postgres from 89.185.45.x port 55234 ssh2
11  
12  # Counting attack attempts
13  grep "Failed password" /var/log/auth.log | wc -l
14  # Result: 15,847 attempts in just 24 hours!
15  
16  # Unique attacking IPs
17  grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort -u | wc -l
18  # Result: 1,258 different IP addresses

This was just one day on a fresh server with nothing important on it. The internet truly is a hostile environment, and security isn't optional,it's essential for survival.

Understanding Attack Vectors

As I researched these attacks, I learned about common vectors that attackers use:

1. Brute Force Attacks

Automated bots trying common usernames and passwords:

Most Common Attack Patterns I Observedtext
1Common usernames attempted:
2  - root (45% of attempts)
3  - admin (12%)
4  - ubuntu (8%)
5  - test/test1/testing (6%)
6  - postgres/mysql/oracle (5%)
7  - user/usuario (4%)
8  - pi (Raspberry Pi default) (3%)
9  
10  Common passwords attempted:
11  - 123456, password, 12345678
12  - admin, root, test
13  - Password1, P@ssw0rd
14  - Keyboard patterns: qwerty, 1qaz2wsx
15  - Dates: 2023, 2024, january
16  
17  Geographic distribution of attacks:
18  - China: 35%
19  - Russia: 18%
20  - Brazil: 12%
21  - India: 8%
22  - USA: 7% (often compromised servers)
23  - Others: 20%

2. Port Scanning

Attackers constantly scan for open ports:

Detecting Port Scansbash
1# Install port scan detection
2  sudo apt install psad
3  
4  # Check what ports are open
5  sudo netstat -tlnp
6  
7  # Common ports attackers target:
8  # 22 (SSH) - Always under attack
9  # 3389 (RDP) - Windows Remote Desktop
10  # 3306 (MySQL) - Database access
11  # 5432 (PostgreSQL) - Database access
12  # 6379 (Redis) - Often unsecured
13  # 27017 (MongoDB) - Default unsecured
14  # 8080, 8081, 8888 - Common web app ports
15  
16  # See who's scanning you
17  sudo tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn) != 0'

Building My First Line of Defense: Firewalls

Understanding firewalls was crucial. I learned to use UFW (Uncomplicated Firewall) as my first defense layer:

Implementing UFW Firewall Rulesbash
1# Basic UFW setup
2  sudo apt install ufw
3  
4  # Default policies: deny all incoming, allow outgoing
5  sudo ufw default deny incoming
6  sudo ufw default allow outgoing
7  
8  # Allow SSH (careful - do this before enabling!)
9  sudo ufw allow 22/tcp comment 'SSH'
10  
11  # Allow web traffic
12  sudo ufw allow 80/tcp comment 'HTTP'
13  sudo ufw allow 443/tcp comment 'HTTPS'
14  
15  # Allow from specific IP only (my home)
16  sudo ufw allow from 192.168.1.100 to any port 22
17  
18  # Rate limiting for SSH
19  sudo ufw limit ssh/tcp comment 'SSH rate limit'
20  
21  # Enable the firewall
22  sudo ufw enable
23  
24  # Check status
25  sudo ufw status verbose
26  
27  # Advanced: Block specific countries (requires GeoIP)
28  # Block IP ranges from specific regions
29  sudo ufw deny from 185.234.219.0/24 comment 'Blocked range'
30  
31  # Application profiles
32  sudo ufw app list
33  sudo ufw allow 'Nginx Full'
34  
35  # Logging
36  sudo ufw logging on
37  sudo ufw logging medium  # low, medium, high, full

SSH Hardening: Beyond Basic Security

SSH is often the primary target, so I learned to harden it properly:

Comprehensive SSH Securitybash
1# Edit SSH configuration
2  sudo nano /etc/ssh/sshd_config
3  
4  # Essential security settings:
5  Port 2222                    # Change from default 22
6  PermitRootLogin no          # Never allow root login
7  PasswordAuthentication no    # Force key-based auth
8  PubkeyAuthentication yes    # Enable public key auth
9  MaxAuthTries 3              # Limit login attempts
10  MaxSessions 2               # Limit concurrent sessions
11  ClientAliveInterval 300     # Disconnect idle sessions
12  ClientAliveCountMax 2       # After 10 minutes
13  AllowUsers nikolas          # Whitelist specific users
14  Protocol 2                  # Use only SSH protocol 2
15  
16  # Advanced settings:
17  StrictModes yes             # Check file permissions
18  IgnoreRhosts yes           # Ignore legacy .rhosts
19  HostbasedAuthentication no  # Disable host-based auth
20  PermitEmptyPasswords no    # Obvious but important
21  X11Forwarding no           # Disable unless needed
22  PrintLastLog yes           # Show last login info
23  
24  # Generate strong SSH keys
25  ssh-keygen -t ed25519 -a 100 -C "nikolas@secure"
26  # -t ed25519: Modern, secure algorithm
27  # -a 100: Key derivation rounds (slower = more secure)
28  
29  # Set up SSH key permissions correctly
30  chmod 700 ~/.ssh
31  chmod 600 ~/.ssh/authorized_keys
32  chmod 600 ~/.ssh/id_ed25519
33  chmod 644 ~/.ssh/id_ed25519.pub
34  
35  # Restart SSH service
36  sudo systemctl restart sshd
37  
38  # Monitor SSH logs
39  sudo journalctl -u ssh -f

Fail2ban: Automated Attack Response

Manually blocking attackers wasn't scalable. Fail2ban automates this process:

Fail2ban Configurationbash
1# Install Fail2ban
2  sudo apt install fail2ban
3  
4  # Create local configuration
5  sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
6  
7  # Configure SSH protection
8  sudo nano /etc/fail2ban/jail.local
9  
10  [DEFAULT]
11  bantime  = 3600     # Ban for 1 hour
12  findtime  = 600     # Within 10 minutes
13  maxretry = 3        # After 3 attempts
14  ignoreip = 127.0.0.1/8 ::1  # Whitelist localhost
15  
16  [sshd]
17  enabled = true
18  port = 2222         # My custom SSH port
19  filter = sshd
20  logpath = /var/log/auth.log
21  maxretry = 3
22  bantime = 3600
23  
24  # Custom jail for web apps
25  [nginx-limit-req]
26  enabled = true
27  filter = nginx-limit-req
28  action = iptables-multiport[name=ReqLimit, port="http,https"]
29  logpath = /var/log/nginx/error.log
30  findtime = 600
31  maxretry = 10
32  bantime = 7200
33  
34  # Check banned IPs
35  sudo fail2ban-client status
36  sudo fail2ban-client status sshd
37  
38  # Unban an IP (if you lock yourself out)
39  sudo fail2ban-client unban 192.168.1.100
40  
41  # Watch it work
42  sudo tail -f /var/log/fail2ban.log
43  # 2024-03-15 10:23:45 INFO [sshd] Ban 185.234.219.45
44  # 2024-03-15 10:24:12 INFO [sshd] Ban 103.145.23.17

Understanding Encryption: HTTPS and Beyond

Learning about encryption was crucial for protecting data in transit:

Implementing HTTPS with Let's Encryptbash
1# Install Certbot for Let's Encrypt
2  sudo apt install certbot python3-certbot-nginx
3  
4  # Get SSL certificate
5  sudo certbot --nginx -d example.com -d www.example.com
6  
7  # Auto-renewal
8  sudo certbot renew --dry-run
9  
10  # Check certificate
11  echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
12  
13  # Strong SSL configuration for Nginx
14  server {
15      listen 443 ssl http2;
16      server_name example.com;
17  
18      # Modern SSL configuration
19      ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
20      ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
21      
22      # Strong protocols and ciphers
23      ssl_protocols TLSv1.2 TLSv1.3;
24      ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
25      ssl_prefer_server_ciphers off;
26      
27      # HSTS
28      add_header Strict-Transport-Security "max-age=63072000" always;
29      
30      # Other security headers
31      add_header X-Frame-Options "SAMEORIGIN" always;
32      add_header X-Content-Type-Options "nosniff" always;
33      add_header X-XSS-Protection "1; mode=block" always;
34  }
35  
36  # Test SSL configuration
37  curl -I https://example.com
38  nmap --script ssl-enum-ciphers -p 443 example.com

Zero Trust Architecture: Trust Nothing, Verify Everything

The traditional security model of "hard outer shell, soft inside" doesn't work anymore. I learned about Zero Trust principles:

Implementing Zero Trust Conceptsyaml
1# Zero Trust Principles:
2  # 1. Never trust, always verify
3  # 2. Assume breach
4  # 3. Verify explicitly
5  # 4. Use least privilege access
6  
7  # Example: Service Authentication
8  version: '3.8'
9  
10  services:
11    api:
12      image: myapi:latest
13      networks:
14        - internal
15      environment:
16        # Service-to-service authentication
17        - SERVICE_TOKEN=${API_SERVICE_TOKEN}
18        - VERIFY_TOKENS=true
19        - ALLOWED_ORIGINS=https://app.example.com
20      secrets:
21        - api_key
22      deploy:
23        labels:
24          - "traefik.http.middlewares.api-auth.basicauth.users=${API_USERS}"
25          - "traefik.http.routers.api.middlewares=api-auth,rate-limit"
26  
27    database:
28      image: postgres:15
29      networks:
30        - internal
31      environment:
32        # Network isolation - only API can connect
33        - POSTGRES_HOST_AUTH_METHOD=scram-sha-256
34        - POSTGRES_INITDB_ARGS=--auth-host=scram-sha-256
35      command: >
36        postgres
37        -c ssl=on
38        -c ssl_cert_file=/var/lib/postgresql/server.crt
39        -c ssl_key_file=/var/lib/postgresql/server.key
40  
41  networks:
42    internal:
43      internal: true  # No external access

Network Segmentation: Isolation as Security

I learned to segment my network to limit damage from potential breaches:

Network Isolation Strategiesbash
1# Docker network segmentation
2  docker network create --internal database-net
3  docker network create --internal backend-net
4  docker network create frontend-net
5  
6  # Only frontend can reach internet
7  docker run -d --name web --network frontend-net nginx
8  docker run -d --name api --network backend-net myapi
9  docker run -d --name db --network database-net postgres
10  
11  # Connect API to both backend and database networks
12  docker network connect database-net api
13  
14  # VPN-only access to sensitive services
15  # iptables rules to restrict access
16  sudo iptables -A INPUT -p tcp --dport 5432 -s 10.8.0.0/24 -j ACCEPT
17  sudo iptables -A INPUT -p tcp --dport 5432 -j DROP
18  
19  # VLAN setup for physical network segmentation
20  # Guest network: 192.168.10.0/24 - Internet only
21  # IoT network: 192.168.20.0/24 - Isolated
22  # Management: 192.168.30.0/24 - Admin only
23  # Servers: 192.168.40.0/24 - Production

Monitoring and Intrusion Detection

Security isn't just about prevention,it's about detection and response:

Security Monitoring Setupbash
1# Install AIDE (Advanced Intrusion Detection Environment)
2  sudo apt install aide
3  
4  # Initialize AIDE database
5  sudo aideinit
6  sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
7  
8  # Check for changes
9  sudo aide --check
10  
11  # Automated checks via cron
12  echo "0 3 * * * root /usr/bin/aide --check | mail -s 'AIDE Report' admin@example.com" >> /etc/crontab
13  
14  # Log monitoring with Logwatch
15  sudo apt install logwatch
16  sudo logwatch --detail high --service all --range today
17  
18  # Real-time monitoring script
19  #!/bin/bash
20  # Monitor critical files
21  inotifywait -m -r     -e modify,create,delete,move     /etc /var/www /home     --format '%w%f %e %T'     --timefmt '%Y-%m-%d %H:%M:%S'     >> /var/log/file-changes.log
22  
23  # Network monitoring
24  sudo apt install iftop nethogs
25  sudo iftop -i eth0  # Real-time bandwidth
26  sudo nethogs        # Per-process network usage
27  
28  # Security scanning
29  sudo apt install rkhunter
30  sudo rkhunter --check --skip-keypress
31  
32  # Check for rootkits
33  sudo apt install chkrootkit
34  sudo chkrootkit

Security Automation: Making Good Practices Default

I automated security tasks to ensure they actually happen:

Automated Security Scriptsbash
1#!/bin/bash
2  # Daily security audit script
3  
4  echo "=== Security Audit $(date) ===" > /var/log/security-audit.log
5  
6  # Check for security updates
7  echo "Checking for security updates..." >> /var/log/security-audit.log
8  apt list --upgradable 2>/dev/null | grep -i security >> /var/log/security-audit.log
9  
10  # Check for failed login attempts
11  echo -e "
12Failed login attempts:" >> /var/log/security-audit.log
13  grep "Failed password" /var/log/auth.log | tail -20 >> /var/log/security-audit.log
14  
15  # Check open ports
16  echo -e "
17Open ports:" >> /var/log/security-audit.log
18  netstat -tlnp >> /var/log/security-audit.log
19  
20  # Check for unusual processes
21  echo -e "
22High CPU processes:" >> /var/log/security-audit.log
23  ps aux --sort=-%cpu | head -10 >> /var/log/security-audit.log
24  
25  # Check disk usage
26  echo -e "
27Disk usage:" >> /var/log/security-audit.log
28  df -h >> /var/log/security-audit.log
29  
30  # Check for large files (potential data exfiltration)
31  echo -e "
32Large files created in last 24h:" >> /var/log/security-audit.log
33  find / -type f -size +100M -mtime -1 2>/dev/null >> /var/log/security-audit.log
34  
35  # Email the report
36  mail -s "Daily Security Audit" admin@example.com < /var/log/security-audit.log
37  
38  # Automated patching (careful with this!)
39  #!/bin/bash
40  # Auto-update security patches only
41  apt update
42  apt upgrade -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"     $(apt list --upgradable 2>/dev/null | grep -i security | cut -d'/' -f1)

Incident Response: When Things Go Wrong

Despite best efforts, I learned to prepare for breaches:

Incident Response Playbookbash
1# STEP 1: Isolate the threat
2  # Disconnect from network if necessary
3  sudo ifconfig eth0 down
4  
5  # Block attacker IP immediately
6  sudo iptables -I INPUT -s ATTACKER_IP -j DROP
7  
8  # STEP 2: Assess the damage
9  # Check recent commands
10  history | tail -50
11  sudo grep -i 'command' /var/log/auth.log
12  
13  # Check for new users
14  cat /etc/passwd | grep -v '^#' | cut -d: -f1,3,4 | grep -E ':[0-9]{4}:'
15  
16  # Check for unauthorized SSH keys
17  find /home -name authorized_keys -exec cat {} ;
18  
19  # Check for modified files
20  find /etc -type f -mtime -1 -ls
21  find /var/www -type f -mtime -1 -ls
22  
23  # STEP 3: Preserve evidence
24  # Create forensic image
25  dd if=/dev/sda of=/backup/forensic-image.img bs=4M
26  
27  # Save logs
28  tar -czf /backup/logs-$(date +%Y%m%d).tar.gz /var/log/
29  
30  # STEP 4: Clean and restore
31  # Restore from known good backup
32  # Reinstall compromised packages
33  # Change all passwords and keys
34  # Apply all security updates
35  
36  # STEP 5: Learn and improve
37  # Document what happened
38  # Update security procedures
39  # Implement additional monitoring

Best Practices I've Adopted

Through trial, error, and a few close calls, I've developed these security habits:

  • Principle of Least Privilege: Give minimum necessary permissions
  • Defense in Depth: Multiple layers of security
  • Regular Updates: Patch Tuesday is every Tuesday for me
  • Backup Before Changes: Always have a rollback plan
  • Monitor Everything: You can't secure what you can't see
  • Automate Security: Humans forget, scripts don't
  • Assume Breach: Design systems to limit damage
  • Document Everything: Future you will thank present you

Resources That Helped Me

Security is a vast field. These resources helped me build a solid foundation:

  • OWASP: Web application security best practices
  • CIS Benchmarks: Hardening guides for various systems
  • NIST Cybersecurity Framework: Comprehensive security approach
  • r/netsec: Reddit community for security news
  • HackerOne Reports: Learn from real vulnerability disclosures
  • SecurityFocused Podcasts: Darknet Diaries, Security Now

The Security Mindset

The biggest change wasn't technical,it was mental. I now think like an attacker when building systems. Every feature is a potential vulnerability. Every convenience is a security trade-off. This paranoia might seem excessive, but in the hostile environment of the internet, it's necessary for survival.

Security isn't a destination; it's a journey. New vulnerabilities are discovered daily, attack techniques evolve, and the threat landscape constantly shifts. But with solid fundamentals, continuous learning, and healthy paranoia, we can build systems that are resilient against most threats.

"Security is not about making systems impenetrable,that's impossible. It's about making attacks so difficult, time-consuming, and noisy that attackers move on to easier targets. Every security measure is a speed bump, and enough speed bumps make the journey not worth taking."

💬 Comments & Discussion

Share your thoughts, ask questions, or discuss this post. Comments are powered by GitHub Discussions.