<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Regő Botond Ronyecz</title>
    <description>The latest articles on DEV Community by Regő Botond Ronyecz (@rronyecz).</description>
    <link>https://dev.to/rronyecz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3892331%2F07a2081d-bfce-4f3a-8c61-9231cdc92b32.jpg</url>
      <title>DEV Community: Regő Botond Ronyecz</title>
      <link>https://dev.to/rronyecz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rronyecz"/>
    <language>en</language>
    <item>
      <title>DNSSEC: The Developer's Setup Guide (2026)</title>
      <dc:creator>Regő Botond Ronyecz</dc:creator>
      <pubDate>Sat, 09 May 2026 12:20:57 +0000</pubDate>
      <link>https://dev.to/rronyecz/dnssec-the-developers-setup-guide-2026-4hlj</link>
      <guid>https://dev.to/rronyecz/dnssec-the-developers-setup-guide-2026-4hlj</guid>
      <description>&lt;p&gt;DNSSEC has a reputation for being complicated. That reputation is mostly deserved, but the actual setup on modern DNS providers takes about ten minutes. The hard part is understanding what it does and why, so you don't misconfigure it and silently break your domain for a subset of users.&lt;/p&gt;

&lt;p&gt;This is that guide.&lt;/p&gt;




&lt;h2&gt;
  
  
  What DNSSEC actually does
&lt;/h2&gt;

&lt;p&gt;DNS responses have no built-in authentication. When a resolver asks your nameserver "what's the IP for yourapp.com," there's nothing in the original protocol that proves the answer came from you and wasn't modified in transit. Cache poisoning attacks (Kaminsky, 2008) exploited exactly this.&lt;/p&gt;

&lt;p&gt;DNSSEC adds cryptographic signatures to your DNS records. Each record set gets signed with a private key. Resolvers that support DNSSEC validation can verify those signatures against a public key published in your zone. If the answer was tampered with, validation fails and the resolver returns an error instead of a forged response.&lt;/p&gt;

&lt;p&gt;It does not encrypt DNS traffic. Someone watching the network can still see what domains you're querying. That's what DNS over HTTPS (DoH) and DNS over TLS (DoT) are for, which is a separate topic. DNSSEC is about integrity, not confidentiality.&lt;/p&gt;




&lt;h2&gt;
  
  
  The key concepts you need before touching anything
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Zone Signing Key (ZSK)&lt;/strong&gt; signs your actual DNS records (A, MX, CNAME, etc.). It rotates frequently, typically every 30-90 days depending on your provider.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Signing Key (KSK)&lt;/strong&gt; signs the ZSK. It rotates less often and is the one that gets published up the chain to your parent zone (your TLD's nameservers).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DS record&lt;/strong&gt; is a hash of your KSK that lives in the parent zone. This is the link in the chain of trust. When you enable DNSSEC, your registrar takes your DS record and publishes it in the TLD zone. Resolvers walk up this chain to verify your signatures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NSEC/NSEC3&lt;/strong&gt; records prove that a name doesn't exist. Without them, an attacker could return NXDOMAIN for a name that actually exists and you'd have no way to verify they're lying. NSEC3 hashes the names so you're not exposing your full zone contents in the process.&lt;/p&gt;

&lt;p&gt;If this sounds like a lot, managed DNSSEC on most providers handles all of it for you. You enable it, copy a DS record to your registrar, and the provider rotates keys automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setup by provider
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Cloudflare
&lt;/h3&gt;

&lt;p&gt;Cloudflare's DNSSEC is one click. Go to DNS &amp;gt; Settings &amp;gt; DNSSEC and enable it. Cloudflare gives you a DS record to add at your registrar. That's it. Key rotation is automatic and you never have to think about it again.&lt;/p&gt;

&lt;p&gt;The one thing to check: if you're using Cloudflare as a proxy (orange cloud), DNSSEC only covers the DNS layer. The traffic between Cloudflare and your origin is a separate concern.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS Route 53
&lt;/h3&gt;

&lt;p&gt;Route 53 added managed DNSSEC in 2020. In the console, go to your hosted zone, select DNSSEC signing, and enable it. AWS creates a KSK backed by a KMS key in your account, which you can see and control.&lt;/p&gt;

&lt;p&gt;After enabling, Route 53 shows you the DS record. You add that record at your domain registrar. If your registrar is Route 53 as well, there's a button to do it automatically.&lt;/p&gt;

&lt;p&gt;One Route 53 gotcha: the KMS key has to be in &lt;code&gt;us-east-1&lt;/code&gt;. If your infrastructure is in another region, the key still needs to live there. This surprises people.&lt;/p&gt;

&lt;h3&gt;
  
  
  Google Cloud DNS
&lt;/h3&gt;

&lt;p&gt;Go to your Cloud DNS zone, click DNSSEC, enable it. Google manages key rotation automatically. You get a DS record to copy to your registrar. Same pattern as the others.&lt;/p&gt;

&lt;h3&gt;
  
  
  Self-hosted BIND or NSD
&lt;/h3&gt;

&lt;p&gt;This is where it gets manual. You need to generate your ZSK and KSK with &lt;code&gt;dnssec-keygen&lt;/code&gt;, sign your zone with &lt;code&gt;dnssec-signzone&lt;/code&gt;, and set up automated re-signing before signatures expire. If you're running your own nameservers and haven't done this before, the official BIND documentation is the right starting point. The managed provider path is meaningfully easier.&lt;/p&gt;




&lt;h2&gt;
  
  
  The DS record and your registrar
&lt;/h2&gt;

&lt;p&gt;This step is where most DNSSEC setups fail. Enabling signing on your DNS provider is only half the job. The DS record has to be published in the parent zone (the TLD), and that happens through your registrar.&lt;/p&gt;

&lt;p&gt;Every registrar has a different UI for this. You're looking for something called "DNSSEC," "DS records," or "domain security." You'll paste in four fields: key tag, algorithm, digest type, and digest. These come directly from your DNS provider after you enable signing.&lt;/p&gt;

&lt;p&gt;If you change DNS providers later, you have to update the DS record at your registrar before you disable DNSSEC on the old provider. The failure mode is ugly: resolvers that validate DNSSEC will return SERVFAIL for your domain, which looks like your site is down to roughly 30% of users (the ones whose resolvers validate). The other 70% will see nothing wrong. This makes it hard to diagnose.&lt;/p&gt;




&lt;h2&gt;
  
  
  Checking your setup
&lt;/h2&gt;

&lt;p&gt;After enabling DNSSEC and adding the DS record, give it 15-30 minutes to propagate, then verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check if your zone is signed&lt;/span&gt;
dig DNSKEY yourapp.com +short

&lt;span class="c"&gt;# Check if the DS record is in the parent zone&lt;/span&gt;
dig DS yourapp.com @8.8.8.8 +short

&lt;span class="c"&gt;# Full validation check&lt;/span&gt;
dig yourapp.com +dnssec +short
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a more readable output, &lt;a href="https://dnsviz.net" rel="noopener noreferrer"&gt;dnsviz.net&lt;/a&gt; generates a visual graph of your DNSSEC chain of trust. It's the clearest way to see if something is broken.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dane.sys4.de" rel="noopener noreferrer"&gt;DANE Validator&lt;/a&gt; is useful if you're also doing TLSA records for email.&lt;/p&gt;




&lt;h2&gt;
  
  
  What breaks when you get it wrong
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Signature expiry.&lt;/strong&gt; DNSSEC signatures have an expiration date. If your provider doesn't auto-rotate and you forget to re-sign, signatures expire and validating resolvers start returning SERVFAIL. This has taken down larger domains than you'd expect. With a managed provider, this is their problem. On self-hosted DNS, put re-signing on a cron job with monitoring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DS/DNSKEY mismatch.&lt;/strong&gt; If you publish a DS record at your registrar that doesn't match the KSK on your nameserver, validation fails for everyone. This usually happens during a provider migration where someone enabled DNSSEC on the new provider before updating the DS record.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Removing DNSSEC incorrectly.&lt;/strong&gt; If you want to disable DNSSEC: remove the DS record at your registrar first, wait for TTL to expire, then disable signing on your provider. Doing it in the wrong order is the same failure mode as the migration problem above.&lt;/p&gt;




&lt;h2&gt;
  
  
  Monitoring after setup
&lt;/h2&gt;

&lt;p&gt;DNSSEC is one of those things that works silently when it's right and breaks loudly when it's wrong. The breakage is often partial, which makes it worse to debug. Automated monitoring that continuously checks your DNSSEC chain and alerts you if signatures are about to expire or if the DS record stops matching is worth having.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://zerohook.org" rel="noopener noreferrer"&gt;ZeroHook&lt;/a&gt; monitors DNS record changes and flags anomalies, including DNSSEC issues, without you having to remember to check manually: &lt;a href="https://zerohook.org" rel="noopener noreferrer"&gt;zerohook.org&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;DNSSEC signs your DNS records so resolvers can verify the answers haven't been tampered with. On managed providers (Cloudflare, Route 53, Google Cloud DNS), setup is: enable signing, copy DS record to registrar, done. The common failure modes are forgetting the DS record step, and misconfiguring during provider migrations.&lt;/p&gt;

&lt;p&gt;If you're on a managed provider and haven't enabled it yet, you can do it right now. It takes ten minutes and you're protected against a whole class of attacks that otherwise have no defense at the DNS layer.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Part of an ongoing series on DNS security. Previous posts: DNS hijacking · Certificate Transparency logs · Subdomain takeover and dangling DNS&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>dns</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>DNS hijacking: when someone else answers in your domain's name</title>
      <dc:creator>Regő Botond Ronyecz</dc:creator>
      <pubDate>Sat, 09 May 2026 03:39:20 +0000</pubDate>
      <link>https://dev.to/rronyecz/dns-hijacking-when-someone-else-answers-in-your-domains-name-314k</link>
      <guid>https://dev.to/rronyecz/dns-hijacking-when-someone-else-answers-in-your-domains-name-314k</guid>
      <description>&lt;p&gt;Your users type your domain into their browser. They get a login page that looks exactly like yours. They enter their credentials. You never see any of it.&lt;/p&gt;

&lt;p&gt;That's DNS hijacking. No one broke into your servers. No one touched your code. They just changed where your domain points.&lt;/p&gt;




&lt;h2&gt;
  
  
  How DNS actually works (the part that matters)
&lt;/h2&gt;

&lt;p&gt;When someone visits &lt;code&gt;yourapp.com&lt;/code&gt;, their browser asks a DNS resolver: "what IP address is this?" The resolver checks its cache, and if it doesn't have an answer, it walks up the DNS hierarchy until it finds one. Your authoritative nameserver, the one you control through your registrar, gives the final answer.&lt;/p&gt;

&lt;p&gt;The whole process takes milliseconds and happens invisibly. It's also built on a foundation of trust. DNS was designed in 1983, when the internet was a handful of universities sharing files. Authentication was an afterthought added decades later, and most of the internet still doesn't use it.&lt;/p&gt;

&lt;p&gt;That gap is where hijacking lives.&lt;/p&gt;




&lt;h2&gt;
  
  
  The three ways it actually happens
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Registrar account compromise
&lt;/h3&gt;

&lt;p&gt;This is the most common and the most damaging. Your domain registrar account gets compromised, and the attacker changes your nameservers to ones they control. Every DNS query for your domain now goes to their server. They answer however they want.&lt;/p&gt;

&lt;p&gt;From the outside, nothing looks wrong. The domain name is yours. The WHOIS still shows your company. Users have no way of knowing they're talking to the wrong server.&lt;/p&gt;

&lt;p&gt;The 2019 Sea Turtle campaign, attributed to a nation-state actor, used exactly this method to target government and military domains across the Middle East and North Africa. They didn't attack the targets directly. They compromised registrars and DNS providers upstream, then redirected traffic to collect credentials. Some victims went months without noticing.&lt;/p&gt;

&lt;h3&gt;
  
  
  DNS cache poisoning
&lt;/h3&gt;

&lt;p&gt;Resolvers cache DNS responses to avoid asking the same question twice. Cache poisoning tricks a resolver into storing a fake answer, so every user who asks that resolver for your domain gets sent to the wrong IP.&lt;/p&gt;

&lt;p&gt;The classic attack exploits the fact that DNS uses UDP, which has no built-in verification. An attacker who can guess the query ID (a 16-bit number, so 65,536 possibilities) can inject a fake response before the real one arrives. Kaminsky's 2008 disclosure showed this was practical at scale. The patch was randomizing the source port on top of the query ID, which raised the guessing space to around 2 billion. Better, but not foolproof.&lt;/p&gt;

&lt;h3&gt;
  
  
  BGP hijacking with DNS as a side effect
&lt;/h3&gt;

&lt;p&gt;Border Gateway Protocol is how internet routers know which paths to use. It's also almost entirely based on trust between autonomous systems. When a network announces that it owns an IP range it doesn't, traffic for those IPs can get rerouted through the attacker's infrastructure.&lt;/p&gt;

&lt;p&gt;In 2018, attackers briefly hijacked the BGP routes for Amazon's Route 53 DNS service. They redirected DNS queries for MyEtherWallet to a server they controlled, which served a fake version of the site and collected around $150,000 in cryptocurrency in two hours. The DNS records themselves were never touched.&lt;/p&gt;




&lt;h2&gt;
  
  
  What attackers do with it
&lt;/h2&gt;

&lt;p&gt;Credential harvesting is the obvious one. Serve a convincing copy of your login page, collect usernames and passwords, pass the credentials through to the real site so users don't notice anything is off.&lt;/p&gt;

&lt;p&gt;But it goes further than that. If your domain is used for email (MX records), an attacker who controls your DNS controls where your email goes. Password reset links, internal notifications, customer data, all of it can be redirected.&lt;/p&gt;

&lt;p&gt;HTTPS doesn't save you here. An attacker who controls your DNS can request a valid TLS certificate for your domain from any CA using HTTP-01 or DNS-01 validation. The padlock in the browser will be green. The certificate will show your domain name. It will be completely legitimate from the browser's perspective.&lt;/p&gt;




&lt;h2&gt;
  
  
  Signs something is wrong
&lt;/h2&gt;

&lt;p&gt;Most teams find out from users. "Your site looks weird" or "my password stopped working" are common first signals, by which point the damage is done.&lt;/p&gt;

&lt;p&gt;What to actually watch:&lt;/p&gt;

&lt;p&gt;Your NS records should never change unless you're deliberately migrating DNS providers. Set up monitoring for them. If your authoritative nameservers change without a ticket in your system, something is wrong.&lt;/p&gt;

&lt;p&gt;TTL spikes are suspicious. Attackers sometimes lower TTLs before a hijacking to make the switch propagate faster and to make rollback harder. A sudden drop in TTL across your zone is worth investigating.&lt;/p&gt;

&lt;p&gt;Response time changes. If your DNS responses start coming from unexpected geographic locations or taking longer than usual, a resolver somewhere is getting wrong answers.&lt;/p&gt;

&lt;p&gt;Certificate transparency logs, which we covered in the previous post on CT logs, will show you if a certificate was issued for your domain from an unexpected CA. This is often one of the first visible signs of an active hijack.&lt;/p&gt;

&lt;p&gt;Tools like &lt;a href="https://zerohook.org" rel="noopener noreferrer"&gt;ZeroHook&lt;/a&gt; monitor your DNS records continuously and alert you when something changes, NS records, A records, MX records, anything. The window between a hijack starting and you noticing it manually is often days. Automated monitoring closes that window considerably. Worth setting up: &lt;a href="https://zerohook.org" rel="noopener noreferrer"&gt;zerohook.org&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to actually protect yourself
&lt;/h2&gt;

&lt;p&gt;Lock your domain at the registrar. Most registrars offer a "registrar lock" or "transfer lock" that prevents nameserver changes without an additional out-of-band confirmation. Enable it. Some registrars also offer registry lock, which requires a phone call or signed document to make changes. For critical domains, that friction is worth it.&lt;/p&gt;

&lt;p&gt;Enable DNSSEC on your zone. DNSSEC adds cryptographic signatures to DNS records, so resolvers can verify that the answer they received came from your authoritative server and wasn't tampered with in transit. Adoption is still patchy, but it defends against cache poisoning and some man-in-the-middle attacks.&lt;/p&gt;

&lt;p&gt;Harden your registrar account. Use a strong unique password, enable MFA, and restrict access to the minimum number of people who actually need it. The Sea Turtle campaign worked because registrar accounts are often treated as low-value administrative accounts rather than the critical infrastructure they are.&lt;/p&gt;

&lt;p&gt;Use CAA records to restrict which certificate authorities can issue certs for your domain. If your CAA record says only Let's Encrypt can issue for &lt;code&gt;yourapp.com&lt;/code&gt;, a hijacker using a different CA will get rejected. It's not foolproof but it raises the bar.&lt;/p&gt;

&lt;p&gt;Monitor, not just your servers but your DNS. Uptime monitoring tells you when your site is down. It doesn't tell you that your site is up but serving someone else's content.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;DNS hijacking doesn't require access to your servers or your code. It requires access to wherever your domain's DNS records live, which is usually a registrar account protected by a password and maybe SMS two-factor.&lt;/p&gt;

&lt;p&gt;The attack is invisible to users. HTTPS doesn't stop it. You can lose credentials, email, and customer trust before anyone on your team notices.&lt;/p&gt;

&lt;p&gt;Lock your domain. Enable DNSSEC. Watch your NS records. Set up monitoring that tells you when your DNS changes, not just when your site goes down.&lt;/p&gt;

</description>
      <category>security</category>
      <category>dns</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Certificate Transparency Logs: How Attackers Map Your Infrastructure Before You Know They're Looking</title>
      <dc:creator>Regő Botond Ronyecz</dc:creator>
      <pubDate>Sat, 09 May 2026 03:28:01 +0000</pubDate>
      <link>https://dev.to/rronyecz/certificate-transparency-logs-how-attackers-map-your-infrastructure-before-you-know-theyre-looking-4095</link>
      <guid>https://dev.to/rronyecz/certificate-transparency-logs-how-attackers-map-your-infrastructure-before-you-know-theyre-looking-4095</guid>
      <description>&lt;p&gt;You deleted the staging server. You closed the Jira ticket. You told your team the migration is done.&lt;/p&gt;

&lt;p&gt;But somewhere out there, a publicly searchable database has been quietly logging every TLS certificate your company has ever issued, including the one for &lt;code&gt;internal-api.yourapp.com&lt;/code&gt; you spun up two years ago and forgot about.&lt;/p&gt;

&lt;p&gt;That database is open to anyone with a browser. Attackers use it every single day.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Certificate Transparency and why does it exist?
&lt;/h2&gt;

&lt;p&gt;Certificate Transparency (CT) is a public, append-only logging system for TLS certificates. It was designed with good intentions: in 2013, Google introduced it after a CA (DigiCert Malaysia) was caught issuing unauthorized certificates for Google's own domains. The idea was to make every certificate publicly auditable so rogue certs could be detected quickly.&lt;/p&gt;

&lt;p&gt;Today, all major browsers require that certificates be submitted to at least two public CT logs before they're considered trusted. That means every certificate issued for your domains, past or present, is recorded in a permanent, searchable, publicly accessible ledger.&lt;/p&gt;

&lt;p&gt;The logs are operated by Google, Cloudflare, DigiSign, and others. You can query them directly at &lt;a href="https://crt.sh" rel="noopener noreferrer"&gt;crt.sh&lt;/a&gt;, or tap into the real-time stream with tools like Certstream.&lt;/p&gt;

&lt;p&gt;This is great for defenders. It's also a goldmine for attackers.&lt;/p&gt;




&lt;h2&gt;
  
  
  The recon phase nobody talks about
&lt;/h2&gt;

&lt;p&gt;Before any actual attack happens, there's reconnaissance. Certificate transparency logs have become one of the most reliable recon techniques out there, because they're passive, legal, and the data is just sitting there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Enumerate every subdomain you've ever had
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://crt.sh/?q=%.yourapp.com&amp;amp;output=json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.[].name_value'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/\*\.//g'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one command returns a complete historical list of every subdomain you've ever issued a certificate for. Not just what's live today, everything, ever.&lt;/p&gt;

&lt;p&gt;That includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;staging.yourapp.com&lt;/code&gt; (the one you decommissioned last spring)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;internal-dashboard.yourapp.com&lt;/code&gt; (set up for a contractor who left)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;beta-v2.yourapp.com&lt;/code&gt; (the failed product launch from 2021)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jenkins.yourapp.com&lt;/code&gt; (please tell me you took this offline)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The attacker didn't scan your network. They didn't need to. You published this list yourself every time you provisioned a certificate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Check which ones are still alive
&lt;/h3&gt;

&lt;p&gt;Once they have the list, it's trivial to check which subdomains still resolve, and more importantly, which ones resolve to something they can claim.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;subdomains.txt | dnsx &lt;span class="nt"&gt;-silent&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-resp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tools like &lt;code&gt;dnsx&lt;/code&gt;, &lt;code&gt;massdns&lt;/code&gt;, and &lt;code&gt;shuffledns&lt;/code&gt; can resolve thousands of subdomains in seconds. The attacker is looking for a specific pattern: a CNAME that still exists in your DNS, pointing at a service that no longer has your app registered on it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Find dangling records and take them over
&lt;/h3&gt;

&lt;p&gt;If &lt;code&gt;staging.yourapp.com&lt;/code&gt; has a CNAME pointing to &lt;code&gt;yourapp-staging.herokuapp.com&lt;/code&gt;, and that Heroku app was deleted six months ago, it's available to claim. Anyone can register a new Heroku app at that address. The attacker now controls a subdomain under your brand, with a valid HTTPS certificate and no browser warnings.&lt;/p&gt;

&lt;p&gt;This isn't theoretical. It has happened to Uber, Microsoft, and hundreds of smaller companies. The &lt;a href="https://github.com/EdOverflow/can-i-take-over-xyz" rel="noopener noreferrer"&gt;EdOverflow/can-i-take-over-xyz&lt;/a&gt; repository tracks dozens of platforms, Heroku, Netlify, GitHub Pages, S3, Fastly, Shopify, Azure, that are all exploitable in exactly this way.&lt;/p&gt;




&lt;h2&gt;
  
  
  What they do once they're in
&lt;/h2&gt;

&lt;p&gt;A subdomain takeover under your domain isn't just an embarrassment. Consider what the attacker actually has.&lt;/p&gt;

&lt;p&gt;A login page at &lt;code&gt;staging.yourapp.com&lt;/code&gt; looks completely legitimate. The SSL padlock is valid. The URL is your brand. Security-aware users who check the URL before entering credentials will see nothing wrong.&lt;/p&gt;

&lt;p&gt;If your session cookies are set on &lt;code&gt;.yourapp.com&lt;/code&gt;, they're readable by any subdomain, including the one the attacker just claimed. Depending on your cookie configuration, this can mean direct session hijacking without ever touching your main application.&lt;/p&gt;

&lt;p&gt;And if your CSP includes &lt;code&gt;*.yourapp.com&lt;/code&gt; as a trusted source (which is common), scripts served from the attacker's subdomain are treated as trusted by your main application. Arbitrary JavaScript, injected from a domain that looks like yours, passing all your security checks.&lt;/p&gt;

&lt;p&gt;Your browser has no way of knowing the subdomain changed hands.&lt;/p&gt;




&lt;h2&gt;
  
  
  The CertStream problem: real-time exposure
&lt;/h2&gt;

&lt;p&gt;CT logs aren't just queryable in retrospect. They're also streamable in real time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://certstream.calidog.io/" rel="noopener noreferrer"&gt;CertStream&lt;/a&gt; exposes a WebSocket feed of every certificate being issued right now, across all major CT logs. Attackers use it to monitor for newly issued certificates matching patterns they care about: your company name, your product, your domain.&lt;/p&gt;

&lt;p&gt;The moment your developer issues a cert for &lt;code&gt;new-feature.yourapp.com&lt;/code&gt;, it appears in that stream. Before the feature is deployed, before any internal announcement, an attacker watching CertStream already knows it exists.&lt;/p&gt;

&lt;p&gt;This matters especially for acquisitions. When you start setting up infrastructure for a company you're acquiring, the subdomain pattern is often a dead giveaway. Competitors and researchers monitor these logs. Developers who issue certs for internal services and assume nobody will find them are usually wrong.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wildcards don't help as much as you think
&lt;/h2&gt;

&lt;p&gt;A common response to subdomain enumeration concerns is switching to wildcard certificates (&lt;code&gt;*.yourapp.com&lt;/code&gt;). If you're not issuing individual certs for each subdomain, they won't appear in CT logs.&lt;/p&gt;

&lt;p&gt;This is partially true. But most organizations issue a mix of wildcard and specific certs. Historical certs from before any wildcard migration are still in the logs forever.&lt;/p&gt;

&lt;p&gt;More importantly, CT logs reveal what subdomains you've certificated, not what's actually exposed. Your DNS zone file is the real source of truth. Wildcard certs don't clean up dangling CNAME records.&lt;/p&gt;

&lt;p&gt;There's also the question of blast radius. A single compromised wildcard key signs everything under your domain. The cert covering &lt;code&gt;*.yourapp.com&lt;/code&gt; is a high-value target.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to audit your exposure
&lt;/h2&gt;

&lt;p&gt;Pull your full historical subdomain list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://crt.sh/?q=%.yourdomain.com&amp;amp;output=json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.[].name_value'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/\*\.//g'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; subdomains.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resolve which ones are still live:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;subdomains.txt | dnsx &lt;span class="nt"&gt;-silent&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-resp&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; live_subdomains.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check CNAMEs for dangling records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;subdomains.txt | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;sub&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;cname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;dig CNAME +short &lt;span class="nv"&gt;$sub&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$cname&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$sub&lt;/span&gt;&lt;span class="s2"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;$cname&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}"&lt;/span&gt; &lt;span class="s2"&gt;"https://&lt;/span&gt;&lt;span class="nv"&gt;$cname&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"404&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;no such app&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;doesn't exist"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"  ⚠ POTENTIALLY DANGLING"&lt;/span&gt;
  &lt;span class="k"&gt;fi
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run subjack for automated takeover checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;subjack &lt;span class="nt"&gt;-w&lt;/span&gt; subdomains.txt &lt;span class="nt"&gt;-t&lt;/span&gt; 100 &lt;span class="nt"&gt;-timeout&lt;/span&gt; 30 &lt;span class="nt"&gt;-o&lt;/span&gt; results.txt &lt;span class="nt"&gt;-ssl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For most teams, this is a one-time audit that surfaces something uncomfortable. For ongoing monitoring, &lt;a href="https://zerohook.org" rel="noopener noreferrer"&gt;ZeroHook&lt;/a&gt; automates the whole thing: it watches your DNS records, flags dangling CNAMEs, and alerts you before someone else finds them. Worth bookmarking: &lt;a href="https://zerohook.org" rel="noopener noreferrer"&gt;zerohook.org&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What to actually fix
&lt;/h2&gt;

&lt;p&gt;Delete the DNS record before you tear down any service. Same day. Not "we'll clean it up next sprint," because that sprint doesn't come.&lt;/p&gt;

&lt;p&gt;Export your zone file and go through it line by line. If you can't explain what a record is for, it probably shouldn't be there.&lt;/p&gt;

&lt;p&gt;Get CT log monitoring in place. CertStream or anything that wraps it will tell you when a certificate is issued for your domains. You want to know before someone else does.&lt;/p&gt;

&lt;p&gt;Check your cookie scope. Session cookies set on &lt;code&gt;.yourapp.com&lt;/code&gt; are readable by any subdomain. Tighten this if you can.&lt;/p&gt;

&lt;p&gt;Review your CSP. Wildcard allowances like &lt;code&gt;*.yourapp.com&lt;/code&gt; are common and dangerous. Enumerate sources explicitly where possible.&lt;/p&gt;

&lt;p&gt;DNS cleanup belongs on your decommissioning checklist, next to revoking API keys and removing IAM roles. It's the same category of problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Every certificate you've ever issued is in a public, searchable, permanent log. Attackers use that log to find subdomains you forgot about, check which ones are still live, and claim the ones pointing at services you've already shut down.&lt;/p&gt;

&lt;p&gt;The recon is free. The takeover is five minutes of work. The damage, phishing campaigns on your domain, session hijacking, CSP bypass, is harder to explain to your users.&lt;/p&gt;

&lt;p&gt;Run the commands above. It takes 20 minutes and you'll almost certainly find something.&lt;/p&gt;

</description>
      <category>security</category>
      <category>dns</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Subdomain Takeover Explained (and How to Fix It)</title>
      <dc:creator>Regő Botond Ronyecz</dc:creator>
      <pubDate>Thu, 23 Apr 2026 20:31:20 +0000</pubDate>
      <link>https://dev.to/rronyecz/subdomain-takeover-explained-and-how-to-fix-it-24be</link>
      <guid>https://dev.to/rronyecz/subdomain-takeover-explained-and-how-to-fix-it-24be</guid>
      <description>&lt;p&gt;You shut down a product. You deleted the Heroku app, tore down the S3 bucket, and removed the Netlify site. But you probably forgot the DNS record pointing to it. &lt;/p&gt;

&lt;p&gt;That subdomain is now up for grabs. &lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with dangling DNS records
&lt;/h2&gt;

&lt;p&gt;When you create &lt;code&gt;staging.yourapp.com&lt;/code&gt; and point it to Heroku, you add a CNAME record mapping your subdomain to &lt;code&gt;yourapp.herokuapp.com&lt;/code&gt;. When you shut down the app, that CNAME stays behind. Heroku lets anyone register a new app at that same &lt;code&gt;.herokuapp.com&lt;/code&gt; address. If an attacker grabs it, they now control everything that loads on &lt;code&gt;staging.yourapp.com&lt;/code&gt;. It runs under your domain, with your SSL cert, and with your brand name sitting right there in the address bar. &lt;/p&gt;

&lt;p&gt;You probably didn't notice because you were busy shipping the next thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is actually dangerous
&lt;/h2&gt;

&lt;p&gt;This isn't a theoretical edge case. It's happened to Uber, Microsoft, and it keeps happening to smaller startups that never bother to audit their DNS. Once someone controls a subdomain, the rest is easy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Phishing:&lt;/strong&gt; A login page at &lt;code&gt;staging.yourapp.com&lt;/code&gt; looks completely legitimate. There are no browser warnings and the HTTPS is valid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cookie theft:&lt;/strong&gt; Session cookies scoped to &lt;code&gt;.yourapp.com&lt;/code&gt; are readable by any subdomain, including the one they just claimed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSP bypass:&lt;/strong&gt; If your Content Security Policy whitelists &lt;code&gt;*.yourapp.com&lt;/code&gt;, the attacker is basically inside the house. Any scripts they serve will count as trusted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your browser has absolutely no way of knowing the subdomain changed hands. &lt;/p&gt;

&lt;h2&gt;
  
  
  Where to look
&lt;/h2&gt;

&lt;p&gt;Any external hosting platform can be a vector. The most common culprits I see are Heroku (app deleted but CNAME stays), GitHub Pages (repo renamed), Netlify, and S3. Fastly, Pantheon, Azure, and Shopify all have the exact same problem. There's a solid community-maintained list at &lt;code&gt;github.com/EdOverflow/can-i-take-over-xyz&lt;/code&gt; that tracks exploitable platforms and their specific error fingerprints. &lt;/p&gt;

&lt;h2&gt;
  
  
  How to check if you're vulnerable
&lt;/h2&gt;

&lt;p&gt;Most teams don't have a full list of their subdomains. You'll need to export your DNS provider's zone file and read through it. Check old CI/CD configs for anywhere you set a CNAME. Finally, hit up &lt;code&gt;crt.sh&lt;/code&gt; (certificate transparency logs) to see every subdomain you've ever issued a cert for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://crt.sh/?q=%.yourapp.com&amp;amp;output=json"&lt;/span&gt; | jq &lt;span class="s1"&gt;'.[].name_value'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have your list, check if the target still exists for each CNAME:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig CNAME staging.yourapp.com
curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://yourapp.herokuapp.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;dig&lt;/code&gt; returns a CNAME and &lt;code&gt;curl&lt;/code&gt; gets a "No such app" or a 404, that's a dangling record. Someone could claim it right now. Also, make sure to check your A records. If you're pointing at an elastic IP that you've decommissioned, that IP might be sitting in a stranger's AWS account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing it
&lt;/h2&gt;

&lt;p&gt;The fix is incredibly straightforward: just delete the DNS record. &lt;/p&gt;

&lt;p&gt;The much harder part is making sure this doesn't keep happening. DNS cleanup usually doesn't make it onto shutdown checklists, but it needs to be treated with the same urgency as revoking API keys. When you decommission a service, delete the DNS record that same day and verify it no longer resolves. If you absolutely need to keep the subdomain, point it at something you control. Even a static page returning a 200 is enough to block a takeover.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools I use for this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ZeroHook&lt;/strong&gt; (&lt;code&gt;zerohook.org&lt;/code&gt;) for auditing DNS and subdomains in one place. It automatically flags dangling records and has a free tier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;crt.sh&lt;/strong&gt; as a starting point for discovery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;subjack&lt;/strong&gt; to automatically scan a list of subdomains for takeover vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;dnsx&lt;/strong&gt; for fast bulk DNS resolution when the list gets long.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;DNS records outlive the services they point to. That's the entire problem. &lt;/p&gt;

&lt;p&gt;Check your subdomains, especially the old ones. If you've never audited your zone file, take 20 minutes and do it this week. You'll almost certainly find something. It's a five-minute fix if you catch it early, and a full-blown incident if you don't.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>security</category>
      <category>dns</category>
    </item>
    <item>
      <title>SPF, DKIM, DMARC: The Developer's Fixing Guide (2026)</title>
      <dc:creator>Regő Botond Ronyecz</dc:creator>
      <pubDate>Thu, 23 Apr 2026 10:48:47 +0000</pubDate>
      <link>https://dev.to/rronyecz/spf-dkim-dmarc-the-developers-fixing-guide-2026-db0</link>
      <guid>https://dev.to/rronyecz/spf-dkim-dmarc-the-developers-fixing-guide-2026-db0</guid>
      <description>&lt;p&gt;You deployed your app. Transactional emails are set up. Users sign up and trigger a welcome email, but it lands in spam or, worse, never arrives.&lt;/p&gt;

&lt;p&gt;This isn't a code issue. It's a DNS configuration problem, and it's more common than you think.&lt;/p&gt;

&lt;p&gt;This guide covers the three records every developer needs to understand: SPF, DKIM, and DMARC. We'll explain what they are, why they matter, and how to fix them.&lt;/p&gt;

&lt;p&gt;THE PROBLEM: ANYONE CAN FAKE YOUR DOMAIN&lt;/p&gt;

&lt;p&gt;Email was designed in the 1980s without any authentication. By default, anyone can send an email claiming to be from &lt;a href="mailto:noreply@yourapp.com"&gt;noreply@yourapp.com&lt;/a&gt;. There's no verification or signature.&lt;/p&gt;

&lt;p&gt;This is why spam filters exist, and why they are so aggressive. If your domain appears untrustworthy due to missing records or misconfigured DNS, Gmail and Outlook will quietly hide your emails.&lt;/p&gt;

&lt;p&gt;SPF, DKIM, and DMARC are the three DNS records that confirm you are actually sending from your domain.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;SPF - "These servers are allowed to send for me"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;SPF (Sender Policy Framework) is a TXT record on your domain that lists which mail servers are allowed to send emails on your behalf.&lt;/p&gt;

&lt;p&gt;When Gmail receives an email from &lt;a href="mailto:noreply@yourapp.com"&gt;noreply@yourapp.com&lt;/a&gt;, it checks your DNS for an SPF record and asks: "Is this server on the allowed list?"&lt;/p&gt;

&lt;p&gt;A typical SPF record looks like this:&lt;/p&gt;

&lt;p&gt;v=spf1 include:sendgrid.net include:_spf.google.com ~all&lt;/p&gt;

&lt;p&gt;Breaking this down:&lt;/p&gt;

&lt;p&gt;v=spf1 is always the version identifier.&lt;br&gt;
include:sendgrid.net means SendGrid's servers are allowed.&lt;br&gt;
include:_spf.google.com means Google Workspace servers are allowed.&lt;br&gt;
~all means anything else is a soft fail — it's suspicious, but not fully rejected.&lt;/p&gt;

&lt;p&gt;The choice between ~all and -all is important. Use ~all while you're setting up. Switch to -all once you're sure every sending service is listed. Never use +all — it allows everyone.&lt;/p&gt;

&lt;p&gt;A common mistake is hitting the 10-lookup limit. SPF has a hard limit of 10 DNS lookups. Each include: counts as one. If you use SendGrid, Mailchimp, Google Workspace, and Salesforce, you'll reach that limit quickly. If you go over, SPF fails even for legitimate emails. Check your lookup count before you deploy.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DKIM - "This email was signed by us"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;DKIM (DomainKeys Identified Mail) adds a cryptographic signature to every outgoing email. The receiving server checks this signature against a public key you publish in DNS.&lt;/p&gt;

&lt;p&gt;Think of it as a wax seal. Anyone can see the letter, but only you have the stamp.&lt;/p&gt;

&lt;p&gt;You publish a TXT record at a selector subdomain:&lt;/p&gt;

&lt;p&gt;selector1._domainkey.yourapp.com  TXT  "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSI..."&lt;/p&gt;

&lt;p&gt;The actual signing happens in your email provider — SendGrid, Postmark, AWS SES, etc. They generate the key pair and give you the public key to add to DNS. You don't create this manually.&lt;/p&gt;

&lt;p&gt;How to set it up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to your email provider's dashboard (in SendGrid, it's Settings &amp;gt; Sender Authentication).&lt;/li&gt;
&lt;li&gt;They'll give you 2-3 DNS records to add.&lt;/li&gt;
&lt;li&gt;Add them to your DNS provider (Cloudflare, Route53, etc.).&lt;/li&gt;
&lt;li&gt;Click Verify in the provider dashboard.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. DKIM setup mostly involves copy-pasting — the complexity is handled by your provider.&lt;/p&gt;

&lt;p&gt;One thing to note: some providers (SendGrid, Mailchimp) use CNAME records for DKIM instead of TXT. Both methods work. Just follow your provider's instructions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DMARC - "Here's what to do if SPF/DKIM fails"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;DMARC (Domain-based Message Authentication, Reporting &amp;amp; Conformance) connects SPF and DKIM and tells receiving servers what to do when authentication fails. It also sends you daily reports — summaries of who is sending email from your domain and whether it passed or failed.&lt;/p&gt;

&lt;p&gt;The record goes at _dmarc.yourapp.com:&lt;/p&gt;

&lt;p&gt;_dmarc.yourapp.com  TXT  "v=DMARC1; p=none; rua=mailto:&lt;a href="mailto:dmarc@yourapp.com"&gt;dmarc@yourapp.com&lt;/a&gt;"&lt;/p&gt;

&lt;p&gt;The key field is p= (policy):&lt;/p&gt;

&lt;p&gt;p=none — do nothing, just report.&lt;br&gt;
p=quarantine — send failures to spam.&lt;br&gt;
p=reject — block failing emails entirely.&lt;/p&gt;

&lt;p&gt;The right rollout order:&lt;/p&gt;

&lt;p&gt;Week 1-2: p=none. Just collect reports and don't block anything.&lt;br&gt;
Week 3-4: Review reports and fix any legitimate sources you missed.&lt;br&gt;
Month 2: p=quarantine. Failing emails go to spam.&lt;br&gt;
Month 3+: p=reject. Once you're confident, implement hard rejection.&lt;/p&gt;

&lt;p&gt;Don't start with p=reject. You risk blocking legitimate emails you didn't know about.&lt;/p&gt;

&lt;p&gt;The reports arrive as XML attachments. They aren't user-friendly. Use a tool to parse them (more on that below). Don't skip this step — reports help you discover misconfigured services or someone spoofing your domain.&lt;/p&gt;

&lt;p&gt;BONUS: TWO MORE RECORDS WORTH KNOWING&lt;/p&gt;

&lt;p&gt;MTA-STS forces other mail servers to use TLS when connecting to yours. Without it, email in transit can be downgraded to unencrypted. It requires a TXT record plus a hosted policy file. It's a bit more setup, but worth it for transport security.&lt;/p&gt;

&lt;p&gt;BIMI allows your logo to appear in Gmail's inbox next to your email. It requires p=quarantine or p=reject DMARC plus a verified mark certificate. It's mostly relevant for marketing emails, but it's a nice trust signal once everything else is in order.&lt;/p&gt;

&lt;p&gt;THE FIX CHECKLIST&lt;/p&gt;

&lt;p&gt;If your emails are going to spam, check the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SPF record exists — dig TXT yourdomain.com | grep spf&lt;/li&gt;
&lt;li&gt;SPF includes all your sending services — SendGrid, Mailchimp, Google, etc.&lt;/li&gt;
&lt;li&gt;SPF lookup count is 10 or under — use an SPF checker&lt;/li&gt;
&lt;li&gt;DKIM is configured in your email provider and DNS records are verified&lt;/li&gt;
&lt;li&gt;DMARC record exists — dig TXT _dmarc.yourdomain.com&lt;/li&gt;
&lt;li&gt;DMARC rua= is set to receive reports&lt;/li&gt;
&lt;li&gt;No duplicate SPF records — you can only have one SPF TXT record per domain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TOOLS I ACTUALLY USE&lt;/p&gt;

&lt;p&gt;ZeroHook (zerohook.org) — Full DNS and email security audit in one place. There's a free tier available. It's worth checking if you have compliance requirements in the future.&lt;/p&gt;

&lt;p&gt;MXToolbox (mxtoolbox.com) — SPF/DKIM/DMARC lookup, blacklist check. Good for a quick check.&lt;/p&gt;

&lt;p&gt;mail-tester.com — Send a test email to get a deliverability score and see specific issues.&lt;/p&gt;

&lt;p&gt;Postmark DMARC Digests (dmarc.postmarkapp.com) — Free DMARC report parser with a clean interface.&lt;/p&gt;

&lt;p&gt;DMARC Analyzer (dmarcanalyzer.com) — More detailed, paid plans for ongoing monitoring.&lt;/p&gt;

&lt;p&gt;Quick CLI checks without leaving the terminal:&lt;/p&gt;

&lt;p&gt;dig TXT yourdomain.com                               (SPF)&lt;br&gt;
dig TXT _dmarc.yourdomain.com                        (DMARC)&lt;br&gt;
dig TXT selector1._domainkey.yourapp.com             (DKIM)&lt;/p&gt;

&lt;p&gt;TL;DR&lt;/p&gt;

&lt;p&gt;Email authentication involves three DNS records that took the internet 20 years to adopt correctly. They aren't glamorous, but getting them right ensures your emails reach people.&lt;/p&gt;

&lt;p&gt;SPF — whitelist your sending servers.&lt;br&gt;
DKIM — cryptographically sign your emails.&lt;br&gt;
DMARC — set a policy and get reports.&lt;/p&gt;

&lt;p&gt;Start with p=none, read the reports for a few weeks, then tighten the policy. Don't skip the reports — they provide the actual signal.&lt;/p&gt;




&lt;p&gt;If you found this helpful or have questions, leave a comment. I'm happy to discuss specific provider setups (AWS SES, SendGrid, Postmark) if you're interested.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>security</category>
      <category>email</category>
    </item>
    <item>
      <title>Your DNS configuration mistakes are quietly breaking your emails</title>
      <dc:creator>Regő Botond Ronyecz</dc:creator>
      <pubDate>Wed, 22 Apr 2026 10:57:11 +0000</pubDate>
      <link>https://dev.to/rronyecz/your-dns-configuration-mistakes-are-quietly-breaking-your-emails-1k55</link>
      <guid>https://dev.to/rronyecz/your-dns-configuration-mistakes-are-quietly-breaking-your-emails-1k55</guid>
      <description>&lt;p&gt;Most people are not aware that their emails end up in spam&lt;br&gt;
due to either wrong DMARC configuration or non-existent SPF record. &lt;br&gt;
This is one of those issues that go unnoticed and are difficult to debug.&lt;/p&gt;

&lt;p&gt;What usually happens is you search for anything on Google,&lt;br&gt;
try five different tools, and are still lost in figuring out&lt;br&gt;
what needs to be fixed. This happens to everyone – it's frustrating.&lt;/p&gt;

&lt;p&gt;ZeroHook was recently discovered in the midst of such an ordeal.&lt;br&gt;
Checks 30+ different items with respect to your email and DNS&lt;br&gt;
configurations and offers solutions on which records need to be added.&lt;/p&gt;

&lt;p&gt;Beta version for now, but definitely worth bookmarking if you &lt;br&gt;
struggle with similar problems.&lt;/p&gt;

&lt;p&gt;zerohook.org&lt;/p&gt;

</description>
      <category>dns</category>
      <category>security</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
