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 logs2sudotail -f /var/log/auth.log
34# 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
1112# Counting attack attempts13grep"Failed password" /var/log/auth.log |wc -l
14# Result: 15,847 attempts in just 24 hours!1516# Unique attacking IPs17grep"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:
1# Install port scan detection2sudoaptinstall psad
34# Check what ports are open5sudonetstat -tlnp
67# Common ports attackers target:8# 22 (SSH) - Always under attack9# 3389 (RDP) - Windows Remote Desktop10# 3306 (MySQL) - Database access11# 5432 (PostgreSQL) - Database access12# 6379 (Redis) - Often unsecured13# 27017 (MongoDB) - Default unsecured14# 8080, 8081, 8888 - Common web app ports1516# See who's scanning you17sudo 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 setup2sudoaptinstall ufw
34# Default policies: deny all incoming, allow outgoing5sudo ufw default deny incoming
6sudo ufw default allow outgoing
78# Allow SSH (careful - do this before enabling!)9sudo ufw allow 22/tcp comment 'SSH'1011# Allow web traffic12sudo ufw allow 80/tcp comment 'HTTP'13sudo ufw allow 443/tcp comment 'HTTPS'1415# Allow from specific IP only (my home)16sudo ufw allow from 192.168.1.100 to any port 221718# Rate limiting for SSH19sudo ufw limit ssh/tcp comment 'SSH rate limit'2021# Enable the firewall22sudo ufw enable2324# Check status25sudo ufw status verbose
2627# Advanced: Block specific countries (requires GeoIP)28# Block IP ranges from specific regions29sudo ufw deny from 185.234.219.0/24 comment 'Blocked range'3031# Application profiles32sudo ufw app list
33sudo ufw allow 'Nginx Full'3435# Logging36sudo ufw logging on
37sudo 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 configuration2sudonano /etc/ssh/sshd_config
34# Essential security settings:5 Port 2222# Change from default 226 PermitRootLogin no # Never allow root login7 PasswordAuthentication no # Force key-based auth8 PubkeyAuthentication yes# Enable public key auth9 MaxAuthTries 3# Limit login attempts10 MaxSessions 2# Limit concurrent sessions11 ClientAliveInterval 300# Disconnect idle sessions12 ClientAliveCountMax 2# After 10 minutes13 AllowUsers nikolas # Whitelist specific users14 Protocol 2# Use only SSH protocol 21516# Advanced settings:17 StrictModes yes# Check file permissions18 IgnoreRhosts yes# Ignore legacy .rhosts19 HostbasedAuthentication no # Disable host-based auth20 PermitEmptyPasswords no # Obvious but important21 X11Forwarding no # Disable unless needed22 PrintLastLog yes# Show last login info2324# Generate strong SSH keys25 ssh-keygen -t ed25519 -a 100 -C "nikolas@secure"26# -t ed25519: Modern, secure algorithm27# -a 100: Key derivation rounds (slower = more secure)2829# Set up SSH key permissions correctly30chmod700 ~/.ssh
31chmod600 ~/.ssh/authorized_keys
32chmod600 ~/.ssh/id_ed25519
33chmod644 ~/.ssh/id_ed25519.pub
3435# Restart SSH service36sudo systemctl restart sshd
3738# Monitor SSH logs39sudo journalctl -u ssh -f
Fail2ban: Automated Attack Response
Manually blocking attackers wasn't scalable. Fail2ban automates this process:
Fail2ban Configurationbash
1# Install Fail2ban2sudoaptinstall fail2ban
34# Create local configuration5sudocp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
67# Configure SSH protection8sudonano /etc/fail2ban/jail.local
910[DEFAULT]11 bantime =3600# Ban for 1 hour12 findtime =600# Within 10 minutes13 maxretry =3# After 3 attempts14 ignoreip =127.0.0.1/8 ::1 # Whitelist localhost1516[sshd]17 enabled =true18 port =2222# My custom SSH port19 filter = sshd
20 logpath = /var/log/auth.log
21 maxretry =322 bantime =36002324# Custom jail for web apps25[nginx-limit-req]26 enabled =true27 filter = nginx-limit-req
28 action = iptables-multiport[name=ReqLimit, port="http,https"]29 logpath = /var/log/nginx/error.log
30 findtime =60031 maxretry =1032 bantime =72003334# Check banned IPs35sudo fail2ban-client status
36sudo fail2ban-client status sshd
3738# Unban an IP (if you lock yourself out)39sudo fail2ban-client unban 192.168.1.100
4041# Watch it work42sudotail -f /var/log/fail2ban.log
43# 2024-03-15 10:23:45 INFO [sshd] Ban 185.234.219.4544# 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:
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.
💬 Comments & Discussion
Share your thoughts, ask questions, or discuss this post. Comments are powered by GitHub Discussions.
💡 Tip: You need a GitHub account to comment. This helps reduce spam and keeps discussions high-quality.